データベース管理の定番ツール phpMyAdmin の 5.2.3 に、WebAuthn の 2FA が署名を検証せずに通ってしまう問題が、Abraxas Labs の研究で指摘されました。当サイトは、この主張を phpMyAdmin 本体の 5.2.3 ソースで独立に確認しました。核心は、WebAuthn の検証を担う外部ライブラリが既定では入らず、署名を暗号検証しない自前の実装(CustomServer)に静かにフォールバックすることです。結果として、MySQL のパスワードを通ったあと、構造だけ整った出鱈目な署名でも第二要素を抜けられます。この記事は、仕組みと「自分が対象か」の見分け方、そして対策を、本体ソースと公式の構成で裏を取って整理します(攻撃手順=PoC は載せません)。認証ライブラリの不備が乗っ取りに直結する例はBetter Auth の SCIM 実装で起きたアカウント乗っ取り、認可の確認が抜ける類型はIDOR とは|認可チェックの抜けを塞ぐ設計、依存の扱いが守りを崩す全体像はサプライチェーン攻撃とは|手口・防御ツール比較・npm 12の新機構まで実践解説にまとめています。

WHAT HAPPENS何が起きるか

任せた WebAuthn が、署名を見ていなかった

  1. 前提

    既定 tarball は webauthn-lib を同梱しない

    web-auth/webauthn-lib は require-dev / suggest で、composer install --no-dev では入らない(本体の composer.json で確認)

  2. フォールバック

    ライブラリが無いと CustomServer に切り替わる

    createServer() が class_exists で判定し、無ければ自前の CustomServer を使う

  3. 欠陥

    CustomServer は署名を暗号検証しない

    challenge・origin・rpIdHash・user-present・credential id は見るが、response.signature を保存済み公開鍵で検証しない

  4. 結果

    MySQL パスワード後、2FA を素通り

    構造さえ合えば署名が出鱈目でも通る。第二要素が実質無効に(研究者評価 CVSS 8.1・CVE 未採番)

出典: phpMyAdmin 5.2.3 本体ソース(WebAuthn.php / CustomServer.php / composer.json)を独立確認、Abraxas Labs の研究(2026-10-29 確認)

30秒でわかる

  • ・何が起きたか:WebAuthn 2FA が署名を暗号検証しない。構造だけ合えば出鱈目な署名でも通る
  • ・原因:webauthn-lib は require-dev/suggestで既定では入らず、署名を見ない CustomServer にフォールバック
  • ・影響:MySQL パスワードの後、第二要素を無効化(研究者評価 CVSS 8.1・PR:L)。初期アクセスは別途必要
  • ・対応:web-auth/webauthn-lib を導入(本検証に切替)。入れないなら 2FA を最後の砦にしない

まず自分の構成がどちらのサーバを使っているかを確かめます。

composer show web-auth/webauthn-lib 2>/dev/null || echo "未インストール → CustomServer(対象)"

ライブラリが入っていなければ、署名を検証しない CustomServer が動いています。これは侵害の判定ではなく、どちらの実装かの確認です。

何が起きるのか

phpMyAdmin は、WebAuthn(FIDO2)の検証を外部ライブラリ web-auth/webauthn-lib に任せる設計です。ところが、このライブラリは composer.json の require-dev と suggest に置かれていて、本番向けの require には入っていません。つまり、公式の配布 tarball をそのまま使う場合や、composer install --no-dev で入れた場合、このライブラリは同梱されません。

WebAuthn(FIDO2) は、物理的なセキュリティキーや端末の生体認証を使う、フィッシングに強い2FAの仕組みです。鍵が持つ秘密鍵で「署名」を作り、サーバは登録時に預かった公開鍵でその署名を検証します。この署名の検証こそが「本人の鍵が確かに応答した」ことの担保で、WebAuthn の背骨です。ここが抜けると、2FA は見かけだけになります。

ライブラリが無いとき、phpMyAdmin の createServer() は、Webauthn\Server クラスの有無を class_exists で見て、無ければ自前の CustomServer を使います(本体の WebAuthn.php で確認)。問題はこの CustomServer にあります。認証時に呼ばれる parseAndValidateAssertionResponse は、credential id が許可リストにあるか、clientData.type が webauthn.get か、challenge が一致するか、origin のホストが一致するか、rpIdHash が一致するか、user-present フラグが立っているか——といった構造の確認は行います。しかし、response.signature を保存済みの credentialPublicKey で暗号検証する処理が、どこにもありません(本体の CustomServer.php で確認)。公開鍵は登録時に保存されるだけで、認証時には使われていません。

なぜ 2FA が素通りするのか

SHOULD VS ACTUALあるべき検証と実際

構造は見るが、真正性は見ない

WebAuthn が検証すべきこと

CustomServer が実際に見ること

WebAuthn が検証すべきこと: response.signature を公開鍵で暗号検証(本人性)

CustomServer が実際に見ること: signature はパースするだけ。公開鍵は使わない

WebAuthn が検証すべきこと: 登録時の credentialPublicKey で照合

CustomServer が実際に見ること: 公開鍵は登録時に保存するが、認証時に未使用

WebAuthn が検証すべきこと: + challenge・origin・rpIdHash・user-present

CustomServer が実際に見ること: この構造チェックだけは行う(ここは正しい)

出典: CustomServer.parseAndValidateAssertionResponse の実装(RELEASE_5_2_3)を確認。PoC/手順は非掲載(2026-10-29)

WebAuthn の検証は、本来「構造の確認」と「署名の暗号検証」の二本立てです。構造の確認は、リプレイや別サイトでの使い回しを防ぐための前提で、challenge や origin の一致を見ます。そして署名の暗号検証が、「登録したその鍵が、今まさに応答した」という本人性を担保します。CustomServer は前者だけを実装し、後者を欠いていました。

その結果、攻撃者が MySQL のパスワード(第一要素)を通したあと、構造の条件(正しい challenge・origin・rpIdHash・user-present・enrolled な credential id)を満たしつつ署名部分は出鱈目な assertion を送っても、検証を通過してしまいます。2FA は実質的に「決まった形の JSON を返すだけ」になり、物理キーを持っているかどうかは問われません。ここでは攻撃に使える具体的な手順(PoC)は示しません。要点は、WebAuthn の背骨である署名検証が、フォールバック実装で抜けていたことです。

どこまでの影響か

誤解を避けるために、影響の範囲を正確に押さえます。これは第一要素を飛ばせるものではありません。攻撃者はまず MySQL のパスワードでログインできる必要があり、その上で第二要素の WebAuthn 2FA を無効化できる、という性質です。研究者の評価は CVSS 3.1 で 8.1、ベクトルは権限一部必要(PR:L)です。到達できれば、得られるのは phpMyAdmin が持つ権限の範囲——つまりその接続で触れるデータベースへのフルアクセスで、ホスト上の PHP シェルではありません。

とはいえ、WebAuthn を 2FA に選ぶ動機は「パスワードが漏れても、物理キーが無ければ入れない」という強い保証です。その保証が、ライブラリを入れ忘れただけで静かに消えているなら、2FA を設定している安心感に反して、パスワード漏洩の時点で守りが崩れます。多層防御の最も頼りにしていた層が、実は検証していなかった——というのが、この問題の重さです。

何を直すか

WHAT TO DO対応の確認項目

webauthn-lib を入れるか、2FA を過信しない

  1. 1.web-auth/webauthn-lib を導入する

    入れると WebauthnLibServer に切り替わり、署名を正しく検証する(CustomServer ではなくなる)

  2. 2.どちらのサーバか確認する

    composer で webauthn-lib の有無を見る。Webauthn\Server が存在すれば本検証、無ければ CustomServer(対象)

  3. 3.入れられないなら強い第二要素と見なさない

    CustomServer のままなら WebAuthn 2FA を防御の最後の砦にしない。到達制限・MySQL 権限最小化で補う

  4. 4.上流の修正・CVE を追う

    現時点で CVE 未採番・ベンダー通知済み。公式の対応が出たら適用する

出典: phpMyAdmin の createServer 実装と composer.json、Abraxas Labs の VENDOR-EMAIL(責任ある開示・2026-10-29 確認)

一番確実なのは、web-auth/webauthn-lib を導入することです。これが入ると、createServer() は WebauthnLibServer を選び、署名の暗号検証を含む正しい WebAuthn 検証が行われます。CustomServer は使われなくなります。

区分 やること
導入 web-auth/webauthn-lib を入れる(WebauthnLibServer に切替=署名を正しく検証)
確認 composer show web-auth/webauthn-lib と class_exists('Webauthn\\Server') で、どちらのサーバか見分ける
代替 入れられないなら WebAuthn 2FA を強い第二要素と見なさない。到達制限・MySQL 権限の最小化で補う
追跡 現時点で CVE 未採番・ベンダー通知済み。公式の対応が出たら適用する

この問題の教訓は、「オプション依存の入れ忘れが、黙って別の(弱い)実装に落ちる」という設計の危うさです。利用者から見れば、WebAuthn 2FA を有効にして鍵も登録しているので、強い保証がかかっているつもりでいます。ところが裏では、ライブラリの有無で検証の中身が入れ替わっていました。自分のスタックでも、「機能が有効か」だけでなく「有効なときに本当に検証しているか」を、一度は実装やログで確かめておく価値があります。セキュリティ機能ほど、オンになっていることと、正しく効いていることは別物として扱うのが安全です。

自分の環境を確認する

版が 5.2.3 で WebAuthn 2FA を使っているなら、どちらのサーバが動いているかを確かめます。

php -r "var_dump(class_exists('Webauthn\\Server'));"

true なら WebauthnLibServer(本検証・対象外)、false なら CustomServer(署名を見ない・対象)です。false だったら、web-auth/webauthn-lib を入れて再確認します。いずれも「いま攻撃されているか」ではなく、どちらの実装で動いているかの確認です。確認できたら、ライブラリを導入し、公式の対応が出たらそれにも追随します。

影響範囲

直接の対象は、phpMyAdmin 5.2.3 で WebAuthn 2FA を使い、かつ web-auth/webauthn-lib を入れていない環境です。公式 tarball や --no-dev のインストールは、この条件に当てはまりやすい構成です。逆に、ライブラリを明示的に入れている環境は、WebauthnLibServer で正しく検証しているため、この問題の対象ではありません。phpMyAdmin は世界中で使われ、DB の管理画面という性質上、守りの要になります。WebAuthn 2FA を「入れたから安心」で終わらせず、実装がどちらで、本当に署名を検証しているかまで確かめることが、確実な備えです。とくに公開しているインスタンスや、多数の開発者が触る共有環境では、第二要素が形だけになっていないかを早めに点検する価値があります。公式の修正・CVE が出たら、本記事も合わせて更新します。

参照ソース