
CVE-2026-73847のPoC - emlog AIアシスタントのCSRFからSQL実行による管理者乗っ取り (CVSS 6.8)
| CVE | CVE-2026-73847 |
| CNA | GitHub |
| アドバイザリ | GHSA-v6wr-4x55-7qp5 |
| CVSS 3.1 | 6.8 中 — AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N |
| CWE | CWE-352 (CSRF), CWE-1275 (SameSite 属性の不適切な設定), CWE-798 (ハードコードされた書き込み確認文字列) |
| 影響を受けるバージョン | emlog pro 2.6.23 まで |
| 報告者 | Dostxodjayev Abdullox (@squeeze440) — CVE レコードの修正待ち。以下を参照 |
emlog pro の管理パネルには、POST /admin/ai.php?action=execute_tool 経由で管理者に代わって SQL を実行できる AI アシスタントが同梱されています。この 1 つのエンドポイントに複数の問題が重なっています。
admin/ 内の他の破壊的操作を伴うファイルはすべて、最初に LoginAuth::checkToken() を呼び出しています(例: admin/media.php:140)。しかし admin/ai.php は呼び出していません。admin/ai.php:152、User::isAdmin())— Origin/Referer のチェックはありません。include/service/ai.php:594: if (trim($confirm_code) !== 'confirm')。偽造リクエストは confirm_code=confirm を送信するだけです。include/service/ai.php:578,589)— 認証されただけのリクエストで任意のテーブルを SELECT できます。blog テーブルだけ(include/service/ai.php:591)— user を含む他のすべてのテーブルは完全に書き込み可能です。password の場合のみ一致します(include/service/ai.php:822-828)— SELECT password AS pwd_hash FROM user は生のハッシュを返します。SameSite 属性がない(include/lib/loginauth.php:99)。この攻撃と確実なクロスサイト配信を隔てる唯一のものは、Chrome のデフォルトの "Lax+POST" 猶予ウィンドウ(ログイン後およそ最初の 2 分間)です。連鎖させると:管理者のブラウザからの 1 つの偽造リクエストで、すべてのテーブル(パスワードハッシュを含む)を読み取り、blog を除くすべてのテーブル(user.password の直接上書きを含む)に書き込むことができます。
poc_raw_impact.sh)SQL/認証バイパスのプリミティブを、CSRF 配信の問題から分離して検証します。自分が管理するローカルインスタンスに対して実行します:
./poc_raw_impact.sh http://TARGET admin '<adminpass>'
このスクリプトは admin としてログインし、列エイリアスのバイパスでパスワードハッシュを取得し、user テーブル経由で管理者パスワードを直接上書きしてから、新しい Cookie ジャーで攻撃者が選択したパスワードを使って再度ログインします。これにより、認証済みリクエストが 1 回エンドポイントに到達すれば、アカウントの完全な乗っ取りが可能であることを証明します。

poc_csrf.html)SameSite の問題を推測ではなく実際のブラウザで検証します。ターゲットとは異なるオリジン(別の IP で十分です — Chrome は異なるリテラル IP を別のサイトとして扱います)から poc_csrf.html を配信し、ログイン後およそ 2 分以内にログイン済みの管理者に開いてもらいます:
python3 -m http.server 8888
# then point poc_csrf.html's form action at your target and get it opened
フォームは読み込み時に自動送信され、confirm_code=confirm を付けた偽造 query_database 呼び出しをクロスサイトで POST します。

実機で検証済み:偽造クロスサイト POST は管理者の実際の認証 Cookie を保持し(sec-fetch-site: cross-site、Cookie 付き)、200 {"code":0,"msg":"ok",...} を返し、注入された行は後続の認証済み読み取りで存在が確認されました。同じリクエストを約 48 分後に同じ(古くなった)Cookie ジャーに対して繰り返すと失敗しました — Cookie は付与されず、サーバーは未認証リダイレクトを返しました。これにより、約 2 分間の Lax+POST ウィンドウが実際の制約であることが確認できます(AC:H に反映)。
emlog_options 内のパスワードハッシュやシークレット(SMTP 資格情報、API キーなど)を含む、すべてのテーブル/列。blog を除くすべてのテーブル(user を含む)へのデータベース全体の書き込み — ロール/パスワード/メールの上書きが可能で、アカウント乗っ取りとしてエンドツーエンドで実証済み。role=admin のアカウントに限定;writer/editor は User::checkRolePermission() でブロックされます。下位ロールからの権限昇格ではありません — ログイン済み管理者による悪意のあるリンクの 1 クリックを、完全かつ静かなサイト乗っ取りに変えます。execute_tool に LoginAuth::checkToken() を追加し、認証 Cookie に SameSite=Strict を設定し、静的 confirm_code 文字列をセッションごとの使い捨てトークンに置き換えてください。完全な修正の詳細はアドバイザリに記載されています。
クレジットに関する注記: CNA としての GitHub は、GHSA 自体が報告者をクレジットし受理していたにもかかわらず、credits エントリなしで CVE レコードを公開しました。2026-08-16 に [email protected] へ訂正リクエストを送信しました。レコードが訂正された場合は、この README を更新します。
アドバイザリが公開され CVE が割り当てられた後に、防御/教育目的で公開しています。所有していない、または明示的にテストを許可されていない emlog インスタンスに対しては実行しないでください。