L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Développement · SKILL.md

performing-serverless-function-security-review

performing-serverless-function-security-review

对 AWS Lambda、Azure Functions 和 GCP Cloud Functions 中的无服务器函数(Serverless Function)执行安全审查,识别过度宽松的执行角色(Execution Role)、不安全的环境变量、注入漏洞和缺失的运行时保护措施。

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: performing-serverless-function-security-review description: > 对 AWS Lambda、Azure Functions 和 GCP Cloud Functions 中的无服务器函数(Serverless Function)执行安全审查,识别过度宽松的执行角色(Execution Role)、不安全的环境变量、注入漏洞和缺失的运行时保护措施。 domain: cybersecurity subdomain: cloud-security tags: [cloud-security, serverless, lambda, azure-functions, cloud-functions, security-review] version: "1.0" author: mahipal license: Apache-2.0

执行无服务器函数安全审查

适用场景

  • 在生产部署前审计无服务器应用时
  • 调查通过函数环境变量或日志潜在数据泄露时
  • 评估受损无服务器函数执行角色的影响范围时
  • 合规审查需要记录无服务器安全控制文档时
  • 为无服务器部署构建安全默认模板时

不适用于:容器或虚拟机安全评估(应使用容器扫描工具)、API 安全测试(应在 API Gateway 层使用 DAST 工具),或实时无服务器威胁检测(应使用带安全代理的 AWS Lambda Extensions)。

前置条件

  • 已配置适当权限的 AWS CLI、Azure CLI 和 gcloud CLI
  • 具有读取函数配置、策略和执行角色的访问权限
  • 已安装 Prowler 或 Checkov,用于自动化无服务器安全扫描
  • 已安装 SAM CLI 或 Serverless Framework,用于本地函数分析
  • 已启用 CloudTrail、Azure Monitor 或 Cloud Audit Logs,用于函数调用监控

工作流程

步骤 1:枚举所有无服务器函数及配置

列出各云提供商的所有函数及其运行时(Runtime)、内存、超时和网络设置。

# AWS Lambda:列出所有函数及关键安全属性
aws lambda list-functions \
  --query 'Functions[*].[FunctionName,Runtime,MemorySize,Timeout,Role,VpcConfig.VpcId,Layers[*].Arn]' \
  --output table

# 检查使用已弃用运行时的函数
aws lambda list-functions \
  --query 'Functions[?Runtime==`python3.7` || Runtime==`nodejs14.x` || Runtime==`dotnetcore3.1`].[FunctionName,Runtime]' \
  --output table

# Azure Functions:列出所有函数应用
az functionapp list \
  --query "[].{Name:name, Runtime:siteConfig.linuxFxVersion, ResourceGroup:resourceGroup, HttpsOnly:httpsOnly}" \
  -o table

# GCP Cloud Functions:列出所有函数
gcloud functions list \
  --format="table(name, runtime, status, httpsTrigger.url, serviceAccountEmail, vpcConnector)"

步骤 2:审计执行角色权限

审查附加到函数的 IAM 角色,识别过度宽松的策略。

# AWS:检查每个 Lambda 函数的执行角色
for func in $(aws lambda list-functions --query 'Functions[*].FunctionName' --output text); do
  role_arn=$(aws lambda get-function-configuration --function-name "$func" --query 'Role' --output text)
  role_name=$(echo "$role_arn" | awk -F'/' '{print $NF}')
  echo "=== $func -> $role_name ==="

  # 列出附加的策略
  aws iam list-attached-role-policies --role-name "$role_name" \
    --query 'AttachedPolicies[*].[PolicyName,PolicyArn]' --output table

  # 检查通配符操作
  for policy_arn in $(aws iam list-attached-role-policies --role-name "$role_name" --query 'AttachedPolicies[*].PolicyArn' --output text); do
    version=$(aws iam get-policy --policy-arn "$policy_arn" --query 'Policy.DefaultVersionId' --output text)
    aws iam get-policy-version --policy-arn "$policy_arn" --version-id "$version" \
      --query 'PolicyVersion.Document' --output json | python3 -c "
import json, sys
doc = json.load(sys.stdin)
for stmt in doc.get('Statement', []):
    actions = stmt.get('Action', [])
    if isinstance(actions, str): actions = [actions]
    resources = stmt.get('Resource', [])
    if isinstance(resources, str): resources = [resources]
    if '*' in actions or any(a.endswith(':*') for a in actions):
        print(f'  警告: {stmt[\"Effect\"]} {actions} 作用于 {resources}')
" 2>/dev/null
  done
done

步骤 3:检查环境变量中的密钥

扫描函数环境变量中是否存在硬编码的凭据(Credential)、API 密钥和数据库连接字符串。

# AWS Lambda:提取环境变量
for func in $(aws lambda list-functions --query 'Functions[*].FunctionName' --output text); do
  envvars=$(aws lambda get-function-configuration --function-name "$func" \
    --query 'Environment.Variables' --output json 2>/dev/null)
  if [ "$envvars" != "null" ] && [ -n "$envvars" ]; then
    echo "=== $func ==="
    echo "$envvars" | python3 -c "
import json, sys, re
vars = json.load(sys.stdin)
sensitive_patterns = [
    r'(?i)(password|secret|key|token|credential|api.?key)',
    r'(?i)(aws.?access|aws.?secret)',
    r'(?i)(database.?url|connection.?string|db.?pass)',
    r'AKIA[0-9A-Z]{16}'
]
for key, value in vars.items():
    for pattern in sensitive_patterns:
        if re.search(pattern, key) or re.search(pattern, str(value)):
            masked = value[:4] + '****' + value[-4:] if len(value) > 8 else '****'
            print(f'  敏感变量: {key} = {masked}')
            break
"
  fi
done

# Azure Functions:检查应用设置
for app in $(az functionapp list --query "[].name" -o tsv); do
  rg=$(az functionapp show --name "$app" --query "resourceGroup" -o tsv)
  echo "=== $app ==="
  az functionapp config appsettings list \
    --name "$app" --resource-group "$rg" \
    --query "[?contains(name,'KEY') || contains(name,'SECRET') || contains(name,'PASSWORD')].{Name:name}" \
    -o table 2>/dev/null
done

步骤 4:审查函数触发器和访问控制

验证函数触发器具有适当的认证和授权配置。

# AWS:检查未认证的 Lambda 函数 URL
aws lambda list-function-url-configs \
  --function-name FUNCTION_NAME \
  --query 'FunctionUrlConfigs[*].[FunctionUrl,AuthType,Cors]' --output table

# 检查允许公开调用的基于资源的策略
for func in $(aws lambda list-functions --query 'Functions[*].FunctionName' --output text); do
  policy=$(aws lambda get-policy --function-name "$func" --query 'Policy' --output text 2>/dev/null)
  if [ -n "$policy" ]; then
    echo "$policy" | python3 -c "
import json, sys
doc = json.loads(sys.stdin.read())
for stmt in doc.get('Statement', []):
    principal = stmt.get('Principal', {})
    if principal == '*' or principal == {'AWS': '*'}:
        print(f'警告: $func 具有公开调用策略: {stmt.get(\"Sid\", \"unnamed\")}')" 2>/dev/null
  fi
done

# GCP:检查未认证的 Cloud Functions
gcloud functions list --format=json | python3 -c "
import json, sys
functions = json.load(sys.stdin)
for func in functions:
    name = func.get('name', '').split('/')[-1]
    trigger = func.get('httpsTrigger', {})
    if trigger and func.get('ingressSettings') == 'ALLOW_ALL':
        print(f'警告: {name} 允许所有入站流量')
"

步骤 5:分析函数代码中的安全漏洞

审查函数代码中的常见无服务器安全问题。

# 下载 Lambda 函数代码进行审查
aws lambda get-function --function-name FUNCTION_NAME \
  --query 'Code.Location' --output text | xargs curl -o function.zip
unzip function.zip -d function-code/

# 使用 Bandit(Python)或 ESLint 安全插件(Node.js)进行扫描
# Python 函数
pip install bandit
bandit -r function-code/ -f json -o bandit-results.json

# Node.js 函数
npm install -g eslint @microsoft/eslint-plugin-sdl
eslint --ext .js function-code/

# 检查常见无服务器漏洞:
# 1. 数据库查询中的 SQL 注入
# 2. 通过 os.system 或 subprocess 的命令注入
# 3. 不安全的反序列化
# 4. 事件数据注入(不可信事件参数)
# 5. 过度的函数权限
grep -rn "os.system\|subprocess\|eval(\|exec(" function-code/ || echo "未发现明显注入模式"
grep -rn "pickle.loads\|yaml.load\b" function-code/ || echo "未发现反序列化风险"

步骤 6:运行自动化无服务器安全扫描

执行 Checkov 和 Prowler,对无服务器资源进行自动化合规检查。

# Checkov 扫描无服务器框架
checkov -d ./serverless-project/ \
  --framework serverless \
  --output json > checkov-serverless.json

# Prowler Lambda 专项检查
prowler aws \
  --checks lambda_function_no_secrets_in_variables \
           lambda_function_url_auth_type \
           lambda_function_using_supported_runtimes \
           lambda_function_not_publicly_accessible \
  -M json-ocsf \
  -o ./prowler-lambda/

核心概念

术语定义
执行角色(Execution Role)无服务器函数执行期间承担的 IAM 角色,定义函数可访问的 AWS/云资源
事件注入(Event Injection)无服务器特有的攻击方式,事件触发载荷中的不可信数据被不安全地用于函数逻辑
函数 URL(Function URL)直接通过 HTTP(S) 端点调用 Lambda 函数(无需 API Gateway)的方式,可能配置为无认证
冷启动(Cold Start)包含容器初始化的首次函数执行过程,安全代理和扩展必须在此期间完成初始化
基于资源的策略(Resource-Based Policy)附加到函数本身的策略,定义谁可以调用函数,与执行角色相互独立
Secrets Manager 集成从密钥管理服务检索敏感配置的模式,而非存储在环境变量中

工具与系统

  • AWS Lambda:主要无服务器计算平台,具有执行角色、层(Layer)和资源策略
  • Checkov:基础设施即代码(IaC)静态分析工具,包含无服务器专项安全策略
  • Prowler:云安全工具,包含 Lambda 权限、公开访问和运行时版本专项检查
  • Bandit:Python 静态分析工具,用于检测函数源代码中的安全问题
  • OWASP Serverless Top 10:针对无服务器架构的安全风险框架

常见场景

场景:具有管理员角色的 Lambda 函数通过环境变量泄露密钥

场景背景:安全审查发现一个 Lambda 函数具有 AdministratorAccess 执行角色,且数据库凭据以明文形式存储在 CloudWatch 日志可见的环境变量中。

方法:

  1. 枚举函数的执行角色,发现附加了 AdministratorAccess 托管策略
  2. 检查环境变量,发现 DB_PASSWORD、API_KEY 和 STRIPE_SECRET_KEY 以明文存储
  3. 审查 CloudWatch 日志,发现调试日志语句中打印了凭据
  4. 创建范围化的 IAM 策略,仅授予所需的特定 DynamoDB 和 S3 操作权限
  5. 将密钥迁移到 AWS Secrets Manager,更新函数在运行时检索
  6. 移除输出敏感数据的调试日志语句
  7. 轮换所有已暴露的凭据,并使用 KMS 启用 Lambda 函数加密

常见陷阱:更改函数执行角色可能导致函数因权限过于严格而中断。请先在演练环境中测试。环境变量变更会触发新的函数版本,确保别名(Alias)和触发器已相应更新。Secrets Manager 调用会增加延迟;在执行上下文中缓存密钥,避免每次调用都进行查询。

输出格式

无服务器函数安全审查
=======================================
账户: 123456789012
审查函数数: 34
审查日期: 2026-02-23

严重发现:
[SRVL-001] 过度宽松的执行角色
  函数: payment-processor
  角色: AdministratorAccess(完全 AWS 访问权限)
  所需权限: DynamoDB:PutItem, S3:GetObject(2 个操作)
  修复建议: 创建仅包含所需权限的范围化策略

[SRVL-002] 环境变量中存在密钥
  函数: payment-processor
  变量: DB_PASSWORD, STRIPE_SECRET_KEY, API_KEY
  风险: 在控制台、API 和 CloudWatch 日志中可见
  修复建议: 迁移到 Secrets Manager,从环境变量中删除

摘要:
  具有管理员角色的函数:              3 / 34
  环境变量中含密钥的函数:            8 / 34
  使用已弃用运行时的函数:            5 / 34
  具有公开访问的函数:                2 / 34
  不在 VPC 内的函数:                28 / 34
  具有通配符权限的函数:             12 / 34
Skills enregistrées