English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

ゲスト
1 / ?

ヘッダーはただの袋

HTTPロギングフレームワークはリクエストヘッダーをキーと値の袋として扱います。ロギングAPIは袋全体を公開します。オペレーターはデバッグのためにヘッダーログを有効にします。リクエストが失敗したとき、ヘッダーが原因を教えてくれるからです。組み込みの拒否リストはありません。ドキュメントに認証情報のフィルタリングはありません。完全なヘッダーがディスクに書き込まれます。

典型的なリクエストに含まれる認証情報ヘッダー:

- Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...(JWTまたはOAuthトークン)

- Cookie: session=abc123; auth=xyz789

- X-API-Key: sk-live-abc123...

- X-Auth-Token: ghp_abc123... (GitHub personal access token pattern)

これらの値はリクエストを認証します。ログファイルに書き込まれると、任意のリクエストを認証できるようになります。

認証情報の流れ

ログファイルに書き込まれた認証情報は一箇所に留まりません。以下のように移動します:

1. Webサーバーが /var/log/nginx/access.log に書き込む

2. ログローテーションエージェント(logrotate)が /var/log/nginx/access.log.1 にコピーする

3. ログシッパー(Fluentd、Filebeat、Logstash)が読み取り、アグリゲーターへ転送する

4. ログアグリゲーター(Elasticsearch、Splunk、Datadog)がインデックス化して保存

5. デフォルトポリシーで30〜90日間保持

この認証情報は5箇所すべてに同時に存在します。セッショントークンを失効させても、ログアグリゲーターから認証情報は削除されません。保持期間中はログアクセス権を持つ人なら誰でも検索・エクスポート・アクセス可能です。

露出期間

メモリ内の認証情報の露出期間:max(セッション期間, プロセス寿命)。セッション:数時間〜数日。プロセス:数時間〜数週間。

ログ内の認証情報の露出期間:max(セッション期間, ログ保持期間)。セッション:数時間〜数日。保持期間:30〜90日。

メモリから盗まれた認証情報は、攻撃者がセッション期間中に存在している必要がありました。一方、ログから盗まれた認証情報は、ログアグリゲーターへのアクセス権さえあれば、保持期間全体にわたって遡及的に取得可能です。

MOAD-0003 vs MOAD-0004

MOAD-0003 (メモリ漏洩): 資格情報がメモリから誤ったリクエストハンドラに漏洩します。プロセスウィンドウ中のみ、スレッドプールを介してアクセス可能です。一時的です。

MOAD-0004 (ログ化されたシークレット): 資格情報がディスク上に存在し、ログローテーション、ログシッピング、ログ集約を通じて永続化されます。ログアクセス権を持つ人なら誰でも、30〜90日間遡及的にアクセス可能です。永続的です。

構造的な違い: 一時的 vs 永続的。修正は異なるレイヤーで動作します。

一時的 vs 永続的

一時的/永続的の区別は、リスクの範囲、修正レイヤー、およびインシデント対応要件を決定します。

MOAD-0004 が MOAD-0003 より高いリスクを伴うのはなぜですか? 各資格情報がどこに存在し、どのくらいの期間存在するかを比較してください。

Credential Denylist at the Serialization Layer

修正方法:シリアライズ層に認証情報の拒否リストを導入します。ヘッダー値がログ出力に到達する前に、ヘッダー名を拒否リストと照合します。一致した場合は値を [REDACTED] に置き換えます。

CREDENTIAL_HEADERS = {
'authorization',
'cookie',
'x-api-key',
'x-auth-token',
'x-csrf-token',
'proxy-authorization',
}

def sanitize_headers(headers: dict) -> dict:
return {
k: '[REDACTED]' if k.lower() in CREDENTIAL_HEADERS else v
for k, v in headers.items()
}

Denylist はシリアライズ層に配置すべきであり、ログクエリ層ではありません。ログクエリによる秘匿化:認証情報がディスクに到達した後に適用されるため、生の値は依然として存在し、表示時のみ隠されます。シリアライズ層による秘匿化:認証情報はディスクに到達しません。生の値はログファイル、ログシッパー、ログ集約器のいずれにも入りません。

Denylist のテスト

3 つのテストパターン:

- Positive: Authorization: Bearer token123 を含むリクエストは、Authorization: [REDACTED] のログエントリを生成する

- ネガティブ: Content-Type: application/json を含むリクエストは、値をそのまま保持したログエントリを生成する

- 大文字小文字を区別しない: AUTHORIZATION: Bearer token123[REDACTED] を生成する(HTTPヘッダー名は大文字小文字を区別しない)

Denylistはメンテナンスが必要です: 新しい認証ヘッダーパターン(例: カスタム X-Service-Auth ヘッダー)には明示的な追加が必要です。この修正は構造的ですが、自己維持ではありません。

Denylistを適用する

あるチームが本番インシデントのデバッグのため、すべてのリクエストヘッダーを含むNginxアクセスログ形式を設定しました。設定内容:

log_format debug_format '$remote_addr - $request - $http_authorization - $http_cookie';
access_log /var/log/nginx/debug.log debug_format;

インシデントを解決し、デバッグ設定を削除する予定だったが、次のデプロイサイクル(7日後)までに本番環境へ変更が反映されなかった。

欠陥を特定せよ。どの認証情報ヘッダーが漏洩する可能性があるか?denylist方式について説明せよ:どこで適用され、何を検査し、何を出力するのか?