mcpField
S
securing-serverless-functions

securing-serverless-functions

github.com/mukul975セキュリティ35.2k103 回インストール8 週間前に更新
リポジトリ

securing-serverless-functions について

Lambda や Azure Functions などのサーバーレス関数を保護・監査するための、開発者やクラウドセキュリティチーム向けガイドです。最小権限、シークレット管理、依存関係スキャン、入力検証、実行時監視を扱います。

主な機能

  1. 01関数の IAM 権限を制限
  2. 02シークレット管理サービスで認証情報を保管
  3. 03CI/CD で依存関係をスキャン
  4. 04イベント入力の検証とサニタイズ
  5. 05実行時監視とログの設定

活用シーン

  1. 01サーバーレス関数の過剰な権限の監査
  2. 02デプロイ前の脆弱な依存関係の検出
  3. 03ハードコードされたシークレットや入力インジェクションの調査
  4. 04関数の異常な動作の監視

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill securing-serverless-functions

インストール後、Claude Code で/securing-serverless-functionsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

LICENSE
references/
api-reference.md
scripts/
agent.py

詳細

サーバーレス関数のセキュリティ保護

使用するタイミング

  • 機密データやクラウド API にアクセスする Lambda 関数または Azure Functions をデプロイするとき
  • 過剰に許可された IAM ロールがないか、既存のサーバーレスワークロードを監査するとき
  • 自動セキュリティスキャンを実施する DevSecOps パイプラインにサーバーレス関数を統合するとき
  • 関数コード内にハードコードされたシークレットや脆弱な依存関係が見つかったとき
  • インジェクションや認証情報の窃取を検出するため、サーバーレスワークロードのランタイム監視を確立するとき

使用しないでください。コンテナベースのコンピューティングのセキュリティ(securing-kubernetes-on-cloud を参照)、API Gateway の設定(implementing-cloud-waf-rules を参照)、またはサーバーレスアーキテクチャの設計判断には使用しないでください。

前提条件

  • デプロイアクセス権のある AWS Lambda、Azure Functions、または GCP Cloud Functions
  • 依存関係スキャンツール(npm audit、Snyk、Dependabot)を備えた CI/CD パイプライン
  • シークレット管理用の AWS Secrets Manager、Azure Key Vault、または HashiCorp Vault
  • 関数監視用の CloudWatch、Application Insights、または Cloud Logging

ワークフロー

ステップ 1:最小権限の IAM ロールを適用する

各 Lambda 関数に専用の IAM ロールを割り当て、アクセスする特定のリソースだけに権限を限定します。関数間で IAM ロールを共有しないでください。

# Create a least-privilege role for a specific Lambda function
aws iam create-role \
  --role-name order-processor-lambda-role \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"Service": "lambda.amazonaws.com"},
      "Action": "sts:AssumeRole"
    }]
  }'

# Attach a scoped policy (not AmazonDynamoDBFullAccess)
aws iam put-role-policy \
  --role-name order-processor-lambda-role \
  --policy-name order-processor-policy \
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": ["dynamodb:PutItem", "dynamodb:GetItem"],
        "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/Orders"
      },
      {
        "Effect": "Allow",
        "Action": ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
        "Resource": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/order-processor:*"
      },
      {
        "Effect": "Allow",
        "Action": ["secretsmanager:GetSecretValue"],
        "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:order-api-key-*"
      }
    ]
  }'
ステップ 2:ハードコードされたシークレットを排除する

環境変数内の平文の認証情報を、シークレット管理サービスへの参照に置き換えます。Lambda 拡張機能または SDK 呼び出しを使用して、実行時にシークレットを取得します。

# INSECURE: Hardcoded credentials in environment variable
# DB_PASSWORD = os.environ['DB_PASSWORD']  # Stored as plaintext in Lambda config

# SECURE: Retrieve from AWS Secrets Manager with caching
import boto3
from botocore.exceptions import ClientError
import json

_secret_cache = {}

def get_secret(secret_name):
    if secret_name in _secret_cache:
        return _secret_cache[secret_name]

    client = boto3.client('secretsmanager')
    response = client.get_secret_value(SecretId=secret_name)
    secret = json.loads(response['SecretString'])
    _secret_cache[secret_name] = secret
    return secret

def lambda_handler(event, context):
    db_creds = get_secret('production/database/credentials')
    db_host = db_creds['host']
    db_password = db_creds['password']
    # Use credentials securely
# Enable encryption at rest for Lambda environment variables
aws lambda update-function-configuration \
  --function-name order-processor \
  --kms-key-arn arn:aws:kms:us-east-1:123456789012:key/key-id
ステップ 3:依存関係の脆弱性をスキャンする

CI/CD パイプラインに自動依存関係スキャンを統合し、デプロイ前に脆弱なパッケージを検出します。

# npm audit for Node.js Lambda functions
cd lambda-function/
npm audit --audit-level=high
npm audit fix

# Snyk scanning in CI/CD pipeline
snyk test --severity-threshold=high
snyk monitor --project-name=order-processor-lambda

# pip-audit for Python Lambda functions
pip-audit -r requirements.txt --desc on --fix

# Scan Lambda deployment package with Trivy
trivy fs --severity HIGH,CRITICAL ./lambda-package/
# GitHub Actions CI/CD security scanning
name: Lambda Security Scan
on: [push, pull_request]
jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install dependencies
        run: npm ci
      - name: Run npm audit
        run: npm audit --audit-level=high
      - name: Snyk vulnerability scan
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
      - name: Scan with Semgrep for code vulnerabilities
        uses: returntocorp/semgrep-action@v1
        with:
          config: p/owasp-top-ten
ステップ 4:入力検証を実装する

すべてのイベント入力データを検証およびサニタイズし、Lambda イベントソースを介した SQL インジェクション、コマンドインジェクション、NoSQL インジェクションなどの攻撃を防ぎます。

import re
import json
from jsonschema import validate, ValidationError

# Define expected input schema
ORDER_SCHEMA = {
    "type": "object",
    "properties": {
        "orderId": {"type": "string", "pattern": "^[a-zA-Z0-9-]{1,36}$"},
        "customerId": {"type": "string", "pattern": "^[a-zA-Z0-9]{1,20}$"},
        "amount": {"type": "number", "minimum": 0.01, "maximum": 999999.99},
        "currency": {"type": "string", "enum": ["USD", "EUR", "GBP"]}
    },
    "required": ["orderId", "customerId", "amount", "currency"],
    "additionalProperties": False
}

def lambda_handler(event, context):
    # Validate API Gateway event body
    try:
        body = json.loads(event.get('body', '{}'))
        validate(instance=body, schema=ORDER_SCHEMA)
    except (json.JSONDecodeError, ValidationError) as e:
        return {
            'statusCode': 400,
            'body': json.dumps({'error': 'Invalid input', 'details': str(e)})
        }

    # Safe to proceed with validated input
    order_id = body['orderId']
    # Use parameterized queries for database operations
ステップ 5:関数 URL と API Gateway の認証を設定する

適切な認証を設定して、関数の呼び出しエンドポイントを保護します。IAM 認証または Cognito 認証なしで Lambda 関数 URL を公開しないでください。

# Secure Lambda function URL with IAM auth (not NONE)
aws lambda create-function-url-config \
  --function-name order-processor \
  --auth-type AWS_IAM \
  --cors '{
    "AllowOrigins": ["https://app.company.com"],
    "AllowMethods": ["POST"],
    "AllowHeaders": ["Content-Type", "Authorization"],
    "MaxAge": 3600
  }'

# API Gateway with Cognito authorizer
aws apigateway create-authorizer \
  --rest-api-id abc123 \
  --name CognitoAuth \
  --type COGNITO_USER_POOLS \
  --provider-arns "arn:aws:cognito-idp:us-east-1:123456789012:userpool/us-east-1_EXAMPLE"
ステップ 6:ランタイム監視とログ記録を有効にする

GuardDuty Lambda Network Activity Monitoring と CloudWatch の構造化ログを設定し、関数の異常な動作を検出します。

# Enable GuardDuty Lambda protection
aws guardduty update-detector \
  --detector-id <detector-id> \
  --features '[{"Name": "LAMBDA_NETWORK_ACTIVITY_LOGS", "Status": "ENABLED"}]'

# Configure Lambda to use structured logging
aws lambda update-function-configuration \
  --function-name order-processor \
  --logging-config '{"LogFormat": "JSON", "ApplicationLogLevel": "INFO", "SystemLogLevel": "WARN"}'

主な概念

用語定義
コールドスタートコンテナのプロビジョニングを含む関数の初回呼び出しです。レイテンシが増加し、キャッシュされたシークレットを利用できない時間が発生します
イベントインジェクションAPI Gateway、S3、SQS、またはその他のイベントソースからの Lambda イベントデータに悪意のある入力を埋め込み、関数を悪用する攻撃です
実行ロール実行中に Lambda が引き受ける IAM ロールで、関数が使用できるすべてのクラウド API 権限を定義します
関数 URLLambda 関数の直接 HTTPS エンドポイントです。IAM 認証または認証なしで設定できます(NONE は安全ではありません)
レイヤー共有コードまたは依存関係を含む Lambda のデプロイパッケージです。脆弱性がないか個別にスキャンする必要があります
予約済み同時実行数関数の同時実行数の上限です。リソース枯渇攻撃の防止に役立ちます
プロビジョニング済み同時実行数コールドスタートのレイテンシを削減し、シークレットのキャッシュを確保する、事前に初期化された関数インスタンスです

ツールとシステム

  • AWS Lambda Power Tuning:セキュリティとパフォーマンスのバランスを取るため、Lambda のメモリとタイムアウトの設定を最適化するオープンソースツールです。
  • Snyk:Lambda の依存関係をスキャンして既知の脆弱性を検出し、自動修正の提案を行う SCA ツールです。
  • Semgrep:サーバーレスに特化したルールを備え、インジェクションの脆弱性、ハードコードされたシークレット、安全でない設定を検出する SAST ツールです。
  • GuardDuty Lambda Protection:Lambda のネットワークアクティビティを監視し、悪意のあるエンドポイントへの接続を検出する AWS サービスです。
  • AWS X-Ray:分散トレーシングサービスです。Lambda の呼び出しにおける不審な外部接続やレイテンシーの異常を検出します。

よくあるシナリオ

シナリオ:API Gateway から Lambda、RDS への経路での SQL インジェクション

コンテキスト:Lambda 関数が API Gateway からユーザー入力を受け取り、文字列連結によって SQL クエリを組み立て、RDS PostgreSQL データベースに対して実行します。攻撃者は API 経由で SQL ペイロードを挿入します。

アプローチ:

  1. Lambda 関数のコードを監査し、SQL クエリで文字列連結が使われている箇所を確認します。
  2. 文字列形式のクエリをすべて、データベースドライバーを使ったパラメーター化クエリに置き換えます。
  3. データベース操作の前に、JSON Schema を使用して入力検証を実装します。
  4. API Gateway に WAF ルールを追加し、一般的な SQL インジェクションのパターンをブロックします。
  5. CI/CD パイプラインに Semgrep を導入し、python.django.security.injection.sql ルールセットを使用します。
  6. GuardDuty Lambda Protection を有効にして、異常なデータベース接続パターンを検出します。

注意点:根本的なコードの脆弱性を修正せずに WAF ルールだけに頼ると、攻撃者はエンコードの細工によって回避できます。ORM メソッドを誤って使用した場合(生のクエリなど)も、インジェクションが可能です。

出力形式

Serverless Security Assessment Report
=======================================
Account: 123456789012
Functions Assessed: 47
Assessment Date: 2025-02-23

CRITICAL FINDINGS:
  [SLS-001] order-processor: SQL injection via string concatenation
    Language: Python 3.12 | Runtime: Lambda
    Vulnerable Code: f"SELECT * FROM orders WHERE id = '{order_id}'"
    Remediation: Use parameterized queries with psycopg2

  [SLS-002] payment-handler: Hardcoded Stripe API key in environment variable
    Key: sk_live_XXXX... (unencrypted)
    Remediation: Migrate to AWS Secrets Manager with KMS encryption

HIGH FINDINGS:
  [SLS-003] 12 functions share the same IAM execution role with s3:*
  [SLS-004] 8 functions have function URLs with AuthType: NONE
  [SLS-005] 23 functions have dependencies with known HIGH CVEs

DEPENDENCY VULNERABILITIES:
  [email protected]:         CVE-2023-45857 (HIGH) - 5 functions affected
  [email protected]:   CVE-2022-23529 (CRITICAL) - 3 functions affected
  [email protected]:       CVE-2021-23337 (HIGH) - 11 functions affected

SUMMARY:
  Critical: 2 | High: 5 | Medium: 12 | Low: 8
  Functions with Least Privilege: 14/47 (30%)
  Functions with Secrets Manager: 19/47 (40%)
  Functions with Input Validation: 22/47 (47%)

コメント