performing-serverless-function-security-review について
クラウドセキュリティ担当者向けのサーバーレス関数レビュー用スキルです。関数の棚卸し、権限とシークレットの確認、コード分析、自動スキャンを、AWS、Azure、Google Cloudに関わる手順に沿って行います。
主な機能
- 01サーバーレス関数設定の棚卸し
- 02実行ロールとアクセス制御の確認
- 03環境変数内のシークレット検査
- 04関数コードのセキュリティ分析
- 05CheckovとProwlerによるスキャン
活用シーン
- 01本番デプロイ前のサーバーレスアプリ監査
- 02設定やログからの情報漏えい調査
- 03実行ロール侵害時の影響範囲評価
- 04コンプライアンス審査用の統制記録
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill performing-serverless-function-security-reviewインストール後、Claude Code で/performing-serverless-function-security-reviewを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEreferences/api-reference.mdscripts/agent.py詳細
サーバーレス関数のセキュリティレビューの実施
使用するタイミング
- 本番環境へのデプロイ前にサーバーレスアプリケーションを監査するとき
- 関数の環境変数やログを介したデータ漏えいの可能性を調査するとき
- サーバーレス関数の実行ロールが侵害された場合の影響範囲を評価するとき
- コンプライアンスレビューでサーバーレスのセキュリティ対策の文書化が必要なとき
- セキュアな設定をデフォルトとするサーバーレスデプロイ用テンプレートを作成するとき
使用しないでください。コンテナや VM のセキュリティ評価には使用しないでください(コンテナスキャンツールを使用してください)。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:すべてのサーバーレス関数と設定を列挙する
クラウドプロバイダー全体の関数を、ランタイム、メモリ、タイムアウト、ネットワーク設定とともに一覧表示します。
# AWS Lambda: List all functions with key security attributes
aws lambda list-functions \
--query 'Functions[*].[FunctionName,Runtime,MemorySize,Timeout,Role,VpcConfig.VpcId,Layers[*].Arn]' \
--output table
# Check for functions using deprecated runtimes
aws lambda list-functions \
--query 'Functions[?Runtime==`python3.7` || Runtime==`nodejs14.x` || Runtime==`dotnetcore3.1`].[FunctionName,Runtime]' \
--output table
# Azure Functions: List all function apps
az functionapp list \
--query "[].{Name:name, Runtime:siteConfig.linuxFxVersion, ResourceGroup:resourceGroup, HttpsOnly:httpsOnly}" \
-o table
# GCP Cloud Functions: List all functions
gcloud functions list \
--format="table(name, runtime, status, httpsTrigger.url, serviceAccountEmail, vpcConnector)"
ステップ 2:実行ロールの権限を監査する
関数にアタッチされた IAM ロールに、過度に許容的なポリシーがないか確認します。
# AWS: Check each Lambda function's execution role
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 ==="
# List attached policies
aws iam list-attached-role-policies --role-name "$role_name" \
--query 'AttachedPolicies[*].[PolicyName,PolicyArn]' --output table
# Check for wildcard actions
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' WARNING: {stmt[\"Effect\"]} {actions} on {resources}')
" 2>/dev/null
done
done
ステップ 3:環境変数にシークレットが含まれていないか確認する
関数の環境変数をスキャンし、ハードコードされた認証情報、API キー、データベース接続文字列を検出します。
# AWS Lambda: Extract environment variables
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' SENSITIVE: {key} = {masked}')
break
"
fi
done
# Azure Functions: Check app settings
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: Check for unauthenticated Lambda function URLs
aws lambda list-function-url-configs \
--function-name FUNCTION_NAME \
--query 'FunctionUrlConfigs[*].[FunctionUrl,AuthType,Cors]' --output table
# Check for resource-based policies allowing public invocation
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'WARNING: $func has public invoke policy: {stmt.get(\"Sid\", \"unnamed\")}')" 2>/dev/null
fi
done
# GCP: Check for unauthenticated 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'WARNING: {name} allows all ingress traffic')
"
ステップ 5:関数コードを分析してセキュリティ上の脆弱性を検出する
関数コードを確認し、一般的なサーバーレスのセキュリティ問題を検出します。
# Download Lambda function code for review
aws lambda get-function --function-name FUNCTION_NAME \
--query 'Code.Location' --output text | xargs curl -o function.zip
unzip function.zip -d function-code/
# Scan with Bandit (Python) or ESLint security plugin (Node.js)
# Python functions
pip install bandit
bandit -r function-code/ -f json -o bandit-results.json
# Node.js functions
npm install -g eslint @microsoft/eslint-plugin-sdl
eslint --ext .js function-code/
# Check for common serverless vulnerabilities:
# 1. SQL injection in database queries
# 2. Command injection via os.system or subprocess
# 3. Insecure deserialization
# 4. Event data injection (untrusted event parameters)
# 5. Excessive function permissions
grep -rn "os.system\|subprocess\|eval(\|exec(" function-code/ || echo "No obvious injection patterns"
grep -rn "pickle.loads\|yaml.load\b" function-code/ || echo "No deserialization risks"
ステップ 6:サーバーレスセキュリティの自動スキャンを実行する
Checkov と Prowler を実行し、サーバーレスリソースのコンプライアンスチェックを自動化します。
# Checkov scan for serverless frameworks
checkov -d ./serverless-project/ \
--framework serverless \
--output json > checkov-serverless.json
# Prowler Lambda-specific checks
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/
主要な概念
| 用語 | 定義 |
|---|---|
| 実行ロール | サーバーレス関数の実行中に関数が引き受ける IAM ロールです。関数がアクセスできる AWS/クラウドリソースを定義します |
| イベントインジェクション | イベントトリガーのペイロードに含まれる信頼できないデータが関数ロジックで安全でない方法で使用される、サーバーレス固有の攻撃です |
| 関数 URL | API Gateway を介さずに Lambda 関数を呼び出すための直接 HTTP(S) エンドポイントです。認証なしで設定されている場合があります |
| コールドスタート | コンテナのプロビジョニングを含む関数の初回実行です。この間にセキュリティエージェントと拡張機能を初期化する必要があります |
| リソースベースのポリシー | 実行ロールとは別に、誰が関数を呼び出せるかを定義する、関数自体にアタッチされたポリシーです |
| Secrets Manager との統合 | 環境変数に保存するのではなく、シークレット管理サービスから機密性の高い設定を取得するパターンです |
ツールとシステム
- AWS Lambda:実行ロール、レイヤー、リソースポリシーを備えた主要なサーバーレスコンピューティングプラットフォームです
- Checkov:サーバーレス固有のセキュリティポリシーを備えた、Infrastructure as Code 用の静的解析ツールです
- Prowler:権限、パブリックアクセス、ランタイムバージョンに関する Lambda 固有のチェックを備えたクラウドセキュリティツールです
- Bandit:関数のソースコードにおけるセキュリティ問題を検出する Python 静的解析ツールです
- OWASP Serverless Top 10:サーバーレスアーキテクチャに特化したセキュリティリスクのフレームワークです
一般的なシナリオ
シナリオ:管理者ロールを持つ Lambda 関数が環境変数経由でシークレットを漏えい
コンテキスト:セキュリティレビューで、AdministratorAccess の実行ロールを持ち、データベースの認証情報が CloudWatch ログから確認できる平文の環境変数に保存されている Lambda 関数が見つかりました。
アプローチ:
- 関数の実行ロールを列挙し、
AdministratorAccessの管理ポリシーを確認します - 環境変数を確認し、平文の
DB_PASSWORD、API_KEY、STRIPE_SECRET_KEYを見つけます - CloudWatch ログを確認し、デバッグログの出力に認証情報が含まれていることを確認します
- 必要な DynamoDB と S3 のアクションのみを許可する、対象を絞った IAM ポリシーを作成します
- シークレットを AWS Secrets Manager に移行し、実行時に取得するよう関数を更新します
- 機密データを出力するデバッグログを削除します
- 漏えいしたすべての認証情報をローテーションし、KMS による Lambda 関数の暗号化を有効にします
注意点:関数の実行ロールを変更すると、新しいロールの制限が厳しすぎる場合に関数が動作しなくなることがあります。まずステージング環境でテストしてください。環境変数を変更すると関数の新しいバージョンが作成されるため、エイリアスとトリガーも更新してください。Secrets Manager の呼び出しは遅延を増やします。呼び出しのたびにシークレットを取得しないよう、実行コンテキスト内でキャッシュしてください。
出力形式
Serverless Function Security Review
=======================================
Account: 123456789012
Functions Reviewed: 34
Review Date: 2026-02-23
CRITICAL FINDINGS:
[SRVL-001] Overly Permissive Execution Role
Function: payment-processor
Role: AdministratorAccess (full AWS access)
Required Permissions: DynamoDB:PutItem, S3:GetObject (2 actions)
Remediation: Create scoped policy with only required permissions
[SRVL-002] Secrets in Environment Variables
Function: payment-processor
Variables: DB_PASSWORD, STRIPE_SECRET_KEY, API_KEY
Risk: Visible in console, API, and CloudWatch logs
Remediation: Migrate to Secrets Manager, remove from env vars
SUMMARY:
Functions with admin roles: 3 / 34
Functions with secrets in env vars: 8 / 34
Functions with deprecated runtimes: 5 / 34
Functions with public access: 2 / 34
Functions without VPC: 28 / 34
Functions with wildcard permissions: 12 / 34