
CVE-2026-100671 のローカル専用概念実証検証ツール。ループバックターゲットに対して Grav Twig ページキャッシュのセッション Cookie 漏洩とリプレイを再現します。
Grav 2.0.25 で修正された Grav の content-Twig/page-cache セッション乗っ取りに対する、最小限のローカル専用検証ツール。
アドバイザリ:
exploit.py は意図的にループバックターゲットに限定されています:
127.0.0.1::1localhostリモートホストを拒否し、ループバックのリダイレクトのみを追跡し、Python 標準ライブラリの HTTP クライアントを使用し、リクエストタイムアウトを適用し、ベアラートークン、クッキー、レスポンスボディを決して出力しません。
自身が所有するか、テストを明示的に許可されている Grav インスタンスに対してのみ使用してください。このスクリプトはローカルラボに公開プルーフページを作成します。ラボが実行間でコンテンツを保持する場合は、テスト後にそのページを削除してください。
get_cookie() が、訪問した管理者のセッションクッキーをサーバーサイドで読み取る。ページ書き込みアカウントには、文書化された低権限の書き込みパスだけが必要です。api.pages.read、admin.*、スーパー管理者アクセスは必要ありません。被害者の管理者は、公開ページを一度訪問するだけで済みます。
2.0.19 から 2.0.24: 出荷時のデフォルト content-Twig 設定で脆弱。2.0.0 から 2.0.18、および 1.7.x: content Twig が明示的に有効化されている場合のみ影響。2.0.25: 修正済み。以下を備えたローカル Grav ラボを実行してください:
この 2 ファイルのリポジトリは、Grav、PHP、プラグイン、アカウントをプロビジョニングしません。
認証情報は環境変数を通じて設定し、ソース管理に入らないようにしてください:
export GRAV_BASE_URL=http://127.0.0.1:8080
export GRAV_WRITER_USERNAME=low
export GRAV_WRITER_PASSWORD='local-writer-password'
export GRAV_ADMIN_USERNAME=admin
export GRAV_ADMIN_PASSWORD='local-admin-password'
python3 exploit.py
ベース URL はループバックのままでなければなりません。デフォルトのルートはランダムです。実行を比較する際には、固定ルートを選択できます:
python3 exploit.py --route /cookie-proof-24
脆弱な場合の期待される結果:
page_create_status=201
admin_login_status=200
victim_page_status=200
attacker_page_status=200
cached_victim_cookie_visible_to_attacker=yes
admin_cookie_value_match=yes
replayed_cookie_api_status=200
result=VULNERABLE
このコマンドは、期待される結果が再現された場合は 0、再現されなかった場合は 1、セットアップまたはトランスポートエラーの場合は 2 で終了します。
同じコマンドを Grav 2.0.25 に対して実行します:
python3 exploit.py --expect fixed
期待される修正済みの動作: 攻撃者から見えるセッション値がなく、セッションリプレイも成功しない。クリーンな修正済み結果は --expect fixed で 0 を終了します。
Grav 2.0.25 以降にアップグレードしてください。古いデプロイメントでは、アドバイザリに以下の一時的な制御が記載されています:
security.twig_content.process_enabled: false で content Twig を無効化する; またはsystem.pages.never_cache_twig: true を設定する;HttpOnly、Secure、SameSite を修正として扱わないでください: 脆弱なクッキー読み取りは Twig レンダリング中にサーバーサイドで発生します。
canhieu によって報告されました。このリポジトリは、すでに公開されているアドバイザリの再現性を支援するものであり、リモートスキャナや認証情報収集ツールではありません。