
phpMyAdmin 5.2.3 - 高 - リモート - CSRF - /sql におけるトークン除去
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-csrf-sql
クラス: CSRF 到達範囲: リモート
phpMyAdmin 5.2.3 (タグ RELEASE_5_2_3、コミット 962857e)。Common.php は checkTokenRequestParam より前にグローバルから PSR-7 リクエストを構築する。不一致時、Sanitize::removeRequestVars は $_POST と $_GET をクリアするが、そのスナップショットはクリアしない。その後 $sql_query は $request->getParsedBodyParam('sql_query') からコピーされる。AJAX POST はトークン不一致で中断する。非 AJAX POST は継続する。SqlController は除去された $_POST['sql_query'] を優先し、そうでなければグローバルを保持する。
phpMyAdmin のセッション Cookie を持つ被害者がいれば十分である。sql_query を付けて、有効なトークンなしで、ajax_request なしで index.php?route=/sql に POST する。SELECT はその MySQL ユーザーとして実行される。5.2.3 のデフォルト CookieSameSite=Strict は多くのクロスサイトブラウザをブロックする。同一サイト、Lax、None、または HTTP 認証では依然として到達する。いずれにせよこれは壊れた CSRF 制御である。
| ID | CVE 未割当 |
| クラス | CSRF |
| 到達範囲 | リモート。デフォルト CookieSameSite=Strict は多くのクロスサイトブラウザをブロックする。同一サイト / Lax / None / HTTP 認証は残る。 |
| CWE | CWE-352 |
| CVSS | High: 8.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N |
| 製品 | phpMyAdmin |
| 影響を受けるバージョン | 5.2.3 タグ RELEASE_5_2_3 (962857e) |
| 認証 | 被害者の phpMyAdmin セッション Cookie (または HTTP 認証)。有効な CSRF トークンなし。 |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1:19240 のみ |
被害者のブラウザに ajax_request なしで phpMyAdmin へ POST させることができる者は誰でも、その MySQL ユーザーとして SQL を実行できる。
| 権限 | メソッド / パス | ラボ実証または推測 |
|---|---|---|
| 被害者の MySQL アカウントとして攻撃者の SQL を実行 (その SQL ボックスの整合性 + 偵察) | POST index.php?route=/sql sql_query=... db=... token なし、ajax_request なし | ラボ実証済み。結果本文に PMA-CSRF-SQL-WITNESS が含まれていた。general log に appuser としての SELECT が記録された |
| AJAX で同じハンドラを中断 | 同じ POST に ajax_request=1 を付ける | ラボ実証済み。Token mismatch。INSERT マーカー行は存在しない。general log はその INSERT を実行しなかった |
除去された $_POST のみを読むハンドラをスキップ | トークンなしで POST /database/structure/drop-table | ラボ実証済み。keepme は依然として存在 |
エクスポート (SaveDir)、パーティション DROP/TRUNCATE、アカウントロック、/config/set、pmadb 作成における同じギャップ | 除去後に PSR-7 ボディを読む任意のハンドラ | 推測。検証はしていない |
このラボで除外: 未認証 PMA (先に Cookie ログインが必要)、AJAX ルート (不一致で終了する)、トークンなしの drop-table、OS シェル。デフォルトの Strict SameSite は、古典的なクロスサイトフォームが Cookie を送信しないことが多いことを意味する。残るものは、同一サイトおよび Lax/None デプロイにおける失敗した CSRF チェックである。
RELEASE_5_2_3 の 8 つの並列ソース探索。Common.php は checkTokenRequestParam() の前に $request = createFromGlobals() を生成する。不一致時、Sanitize::removeRequestVars() は $_POST/$_GET のみをクリアする。非 AJAX は継続する。SqlController は $_POST が空の場合にグローバル $sql_query を使用する。ルートは GET|POST /sql。
誤った方向: AJAX /sql を残存と見なす (Token mismatch で中断する)。drop-table を残存と見なす (そのハンドラは除去された $_POST のみを読む)。デフォルトの Strict SameSite を「CSRF は閉じている」と見なす (制御は依然として壊れており、同一サイト / Lax / None が残る)。
python3 phpmyadmin-csrf-sql-Abraxas-Labs.py
または
cd lab
./run.sh
ループバックのみ: http://127.0.0.1:19240。イメージ phpmyadmin:5.2.3 と mysql:8.0。Compose プロジェクト phpmyadmin-csrf-sql。PoC は同一サイトのループバック POST である (Strict SameSite でも Cookie は送信される)。ウィットネス PMA-CSRF-SQL-WITNESS。
SUCCESS phpmyadmin-csrf-sql sql-ran=yes ajax-abort=yes drop-held=yes PMA-CSRF-SQL-WITNESS
不一致時は、リクエストを空のボディに置き換えるか、AJAX だけでなくすべての POST を拒否する。古いリクエストから sql_query をコピーしない。ログアウトと同様にフェイルクローズする。
962857e)libraries/classes/Common.php トークン除去前のリクエストスナップショットSanitize::removeRequestVars は $_POST/$_GET のみをクリアするSqlController のグローバル $sql_queryGNU Affero GPL v3.0。LICENSE を参照。ループバックラボのみ。無保証。