mcpField
S
security-logging-alerting-failures

security-logging-alerting-failures

github.com/scholarly360セキュリティ2244 回インストール29 週間前に更新
リポジトリ

security-logging-alerting-failures について

security-logging-alerting-failuresは、OWASP A09:2025に基づく監査スキルで、FastAPIとFlaskアプリのログおよびアラート運用を点検します。チェックリスト、構造化ログの指針、アラート閾値、自動スキャン用コマンドを提供します。

主な機能

  1. 01ログインジェクションと機密情報漏えいの確認
  2. 02認証・認可イベントログの点検
  3. 03構造化ログとSIEM互換性の評価
  4. 04アラートルールとインシデント対応の確認
  5. 05CI/CD向け自動スキャンコマンド

活用シーン

  1. 01FastAPIまたはFlaskのセキュリティログ監査
  2. 02ログ内のユーザー入力や秘密情報の検出
  3. 03認証失敗や管理操作の記録確認
  4. 04本番環境のアラート対象範囲の評価

インストール

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

$npx skills add https://github.com/scholarly360/owasp-top10-web-skills --skill security-logging-alerting-failures

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

同梱ファイルreferences/alerting-platforms.mdreferences/remediation-patterns.md

詳細

A09:2025 — セキュリティログ記録とアラートの不備

OWASP ランク: #9(3 回連続でコミュニティ投票により選出)
2025 年に名称を変更:「アラート」を追加しました。アラートのないログ記録では、セキュリティ上の価値はほとんどありません。
統計: 5 CWEs、723 CVEs、平均発生率 3.91%
対象となる CWE: CWE-778、CWE-117、CWE-532、CWE-223、CWE-390


このカテゴリの対象

不備の種類説明
ログ記録の不足監査対象となるイベント(ログイン、アクセス制御の失敗、検証エラー)が記録されない
ログインジェクションユーザー入力がエスケープされずにログメッセージに渡され、ログの偽造が可能になる
ログ内の機密データパスワード、トークン、PII、カード番号がログ出力に書き込まれる
セキュリティ関連情報の欠落エラーや警告が、コンテキスト(IP、ユーザー、タイムスタンプ、アクション)なしで記録される
アラートなしログは存在するものの、インシデント対応に通知するしきい値、ルール、プラットフォームがない

監査チェックリスト — FastAPI と Flask

各セクションを順に確認してください。各項目について、PASS、FAIL、または NOT APPLICABLE を記録してください。

1. ログインジェクション(CWE-117)

ユーザーが制御する入力を、生のままログ文に渡してはいけません。

確認する点:

# VULNERABLE — newline injection, ANSI escape injection
logger.info(f"User logged in: {request.form['username']}")
logger.warning("Failed login for: " + username)

# SAFE — sanitize before logging
import re
safe_username = re.sub(r'[\r\n\x1b]', '_', username)
logger.info("Failed login for: %s", safe_username)

チェックリスト:

  • ログ呼び出しで、生のリクエストデータを f 文字列や + 連結で扱っていない
  • ユーザーが提供するすべてのログ値から改行(\r、\n)を除去している
  • ANSI エスケープコード(\x1b[)を除去している(ターミナルインジェクションを防止)
  • 構造化ログ(JSON 形式)を使用している — フィールドが分離されるため、設計上インジェクションを防止できる

2. ログ内の機密データ(CWE-532)

DEBUG レベルであっても、シークレットをログ出力に含めてはいけません。

フラグを立てるパターン:

# VULNERABLE
logger.debug(f"Auth token: {token}")
logger.info(f"Processing payment for card: {card_number}")
app.logger.debug(request.json)         # May contain password field
print(f"Password reset for {email}, token={reset_token}")

# SAFE
logger.info("Auth token validated for user_id=%s", user_id)
logger.info("Payment processed for user_id=%s, last4=%s", user_id, card_number[-4:])

スキャン対象:

  • password、passwd、secret、token、api_key、authorization ヘッダー値をログに記録していない
  • クレジットカード番号、SSN、メールアドレスとパスワードの組み合わせ全体をログに記録していない
  • request.json / request.form を、フィールドを絞り込まずに丸ごとログに記録していない
  • 本番コードに、機密変数を含む print() 文がない
  • Bandit ルール B506(および類似ルール)が CI/CD でパスしている

3. ログ記録の不足(CWE-778)

以下のイベントは、完全なコンテキストを含むログエントリを必ず生成してください。

必須のログイベント:

イベント最低限必要なフィールド
認証の失敗タイムスタンプ、IP、試行されたユーザー名、ユーザーエージェント
認証の成功タイムスタンプ、IP、user_id、方式(パスワード/OAuth/MFA)
認可の失敗(403)タイムスタンプ、IP、user_id、試行されたリソース、HTTP メソッド
入力検証の失敗タイムスタンプ、IP、user_id、フィールド名(機密情報の場合は値を含めない)、エラー
価値の高いトランザクションタイムスタンプ、user_id、アクション、リソース ID、変更前後の状態
アカウントの変更(パスワードリセット、ロール変更)タイムスタンプ、actor_user_id、target_user_id、変更の種類
管理者の操作タイムスタンプ、admin_user_id、アクション、影響を受けたリソース

FastAPI の実装パターン:

import logging
import structlog  # recommended for structured logs

log = structlog.get_logger()

# In auth endpoint
@router.post("/login")
async def login(credentials: LoginSchema, request: Request):
    user = await authenticate(credentials)
    if not user:
        log.warning(
            "auth.failed",
            ip=request.client.host,
            username=credentials.username,    # OK — username is not a secret
            user_agent=request.headers.get("user-agent"),
        )
        raise HTTPException(status_code=401, detail="Invalid credentials")
    log.info("auth.success", user_id=user.id, ip=request.client.host)

Flask の実装パターン:

from flask import request
import logging

@app.route("/login", methods=["POST"])
def login():
    user = authenticate(request.form["username"], request.form["password"])
    if not user:
        app.logger.warning(
            "auth.failed ip=%s username=%s ua=%s",
            request.remote_addr,
            request.form.get("username"),
            request.user_agent.string,
        )
        return {"error": "Invalid credentials"}, 401

チェックリスト:

  • すべての 401/403 レスポンスに、対応する logger.warning() または logger.error() の呼び出しがある
  • ログエントリにタイムスタンプ(logging による自動付与)、送信元 IP、ユーザー識別子が含まれている
  • パスワードリセットとアカウント変更の処理をログに記録している
  • 管理パネルでの操作を、実行者の識別情報とともにログに記録している
  • 価値の高い業務トランザクションの監査ログエントリを生成している

4. 構造化ログと SIEM との互換性

ログ形式は、可観測性プラットフォーム(ELK、Splunk、Datadog、Sentry)で解析できる必要があります。

FastAPI — structlog + JSON:

# main.py
import structlog
import logging

structlog.configure(
    processors=[
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.stdlib.add_log_level,
        structlog.processors.JSONRenderer(),  # machine-parseable
    ],
    wrapper_class=structlog.BoundLogger,
    logger_factory=structlog.PrintLoggerFactory(),
)

Flask — python-json-logger:

from pythonjsonlogger import jsonlogger

handler = logging.StreamHandler()
handler.setFormatter(jsonlogger.JsonFormatter(
    fmt="%(asctime)s %(levelname)s %(name)s %(message)s"
))
app.logger.addHandler(handler)

チェックリスト:

  • 本番環境のログ出力がプレーンテキストではなく JSON 形式になっている
  • 本番環境でログレベルが DEBUG になっていない(詳細情報が漏えいするため)
  • ログを一元管理プラットフォーム(Sentry、ELK、Splunk、Datadog、CloudWatch)に送信している
  • ログの保持ポリシーがあり、コンプライアンス要件(例:最低 90 日)を満たしている

5. アラート連携

アラート機能のないログ記録は、障害を見逃すことにつながります。有効な監視が行われていることを確認してください。

Sentry(例外アラート):

# FastAPI
import sentry_sdk
from sentry_sdk.integrations.fastapi import FastApiIntegration
sentry_sdk.init(dsn=settings.SENTRY_DSN, integrations=[FastApiIntegration()])

# Flask
from sentry_sdk.integrations.flask import FlaskIntegration
sentry_sdk.init(dsn=settings.SENTRY_DSN, integrations=[FlaskIntegration()])

推奨アラートしきい値:

シグナルアラートの条件
ログイン失敗5 分間に同じユーザー名で 10 回超の失敗
ログイン失敗5 分間に同じ IP から 100 回超の失敗
403 レスポンス1 分間に同じ user_id から 50 件超
500 エラー任意の 1 分間のリクエストの 5% 超
新しい管理者アカウント発生するたびに即時アラート
権限昇格発生するたびに即時アラート

チェックリスト:

  • Sentry または同等のサービスが初期化され、本番環境でイベントを受信している
  • レート制限違反がアラートイベントを発生させる(HTTP 429 レスポンスを返すだけではない)
  • 認証失敗が繰り返された場合にアラートが発生する(ブルートフォース攻撃の検出)
  • 各アラートタイプに対応するアラート対応手順書/プレイブックがある
  • 重要度の高い領域にハニートークンが配置されている(誤検知をほぼゼロに抑えた侵入検知)

自動スキャン

これらのツールを CI/CD の一部として実行してください:

# Static analysis — catches log injection patterns, sensitive data in logs
bandit -r . -t B106,B107,B110 --severity-level medium

# Search for raw request data in log calls
grep -rn "logger\.\(info\|warning\|error\|debug\)" . \
  | grep -E "request\.(form|json|args|data|headers)\[" \
  | grep -v "\.get(" 

# Search for potential sensitive field logging
grep -rn "logger\|logging\|print" . \
  | grep -iE "password|passwd|secret|token|api_key|card|ssn|cvv"

主要な CWE リファレンス

CWE名前Python におけるリスク
CWE-778ログ記録の不足認証/認可の失敗がログに記録されない
CWE-117ログインジェクションロガー呼び出しでユーザー入力を f-string に使用する
CWE-532ログ内の機密情報デバッグ出力にパスワード/トークンが含まれる
CWE-223セキュリティ関連情報の欠落ログに IP/ユーザーのコンテキストがない
CWE-390エラー状態を検出しても対処しない例外を捕捉して握りつぶし、ログにも記録しない

リファレンスファイル

  • references/remediation-patterns.md — 各 CWE の修正コードの完全な修正前/修正後の例
  • references/alerting-platforms.md — Sentry、ELK、Splunk、Datadog の連携ガイド

チェックリストの範囲を超えた詳細な実装支援が必要な場合は、これらを参照してください。

コメント