
Локальная Docker-лаборатория для воспроизведения CVE-2026-3844 — неаутентифицированной произвольной загрузки файлов с последующим выполнением кода (RCE) в плагине WordPress Breeze Cache. Сравнивает уязвимую версию 2.4.4 с исправленной 2.4.5 с использованием изолированных сервисов и PoC с минимальным вредом.
Локальный Docker-стенд для воспроизведения и сравнения поведения CVE-2026-3844 в плагине WordPress Breeze Cache.
В этом репозитории демонстрируется уязвимое поведение в Breeze Cache 2.4.4 и проводится сравнение с исправленным поведением в Breeze Cache 2.4.5. Стенд использует два изолированных сервиса WordPress — один уязвимый и один исправленный, — а также локальный сервер полезной нагрузки внутри Docker-сети.
Эксплойт-Proof of Concept намеренно наименее вредоносный: он не использует веб-шелл, не предоставляет параметр команды, не запускает обратный шелл и не требует чтения файлов изнутри контейнера. Доказательство основано на наблюдаемом HTTP-поведении с хоста.
CVE-2026-3844 затрагивает плагин Breeze Cache для WordPress версии 2.4.4 и ниже. Уязвимый фрагмент кода связан с функцией локального кэширования Gravatar, а именно с потоком выполнения fetch_gravatar_from_remote().
Когда включена опция Breeze Host Files Locally - Gravatars, уязвимые версии могут загружать управляемый атакующим удалённый файл и сохранять его в публично доступной через веб каталоге кэша. Если загруженный файл является PHP, веб-сервер может выполнить его при запросе по HTTP.
Данный стенд воспроизводит это поведение локально:
vuln: WordPress + Breeze Cache 2.4.4patched: WordPress + Breeze Cache 2.4.5payload: локальный сервер полезной нагрузки, доступный только внутри DockersrcsetОжидаемый результат:
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
Host machine
│
├── http://127.0.0.1:8081 -> vuln WordPress + Breeze 2.4.4
├── http://127.0.0.1:8082 -> patched WordPress + Breeze 2.4.5
└── http://127.0.0.1:9100 -> local payload server
Docker network
│
├── vuln -> WordPress vulnerable target
├── patched -> WordPress patched target
├── vuln_db -> MariaDB for vulnerable WordPress
├── patched_db -> MariaDB for patched WordPress
└── payload -> Python static HTTP server
Контейнеры WordPress загружают полезную нагрузку через URL внутри Docker-сети:
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 может извлекать удалённый URL из HTML-разметки, связанной с аватарами, и передавать этот 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.
Данный стенд намеренно держит сервер полезной нагрузки локальным, а не использует публичный хост для полезной нагрузки.
download_url() в WordPress и WordPress HTTP API по умолчанию отклоняют некоторые приватные Docker-имена хостов и нестандартные порты. Публичные эксплойт-скрипты часто используют публичные HTTPS-URL полезной нагрузки, что обходит это ограничение. В данном стенде так не делается.
Чтобы воспроизведение оставалось полностью локальным, скрипт начальной настройки устанавливает небольшой MU-плагин-хелпер, доступный только локально, который:
payload и payload.local80 и 9100Этот хелпер не изменяет исходный код Breeze. И уязвимый, и исправленный сервисы используют настоящие версии плагина Breeze, установленные через WP-CLI.
Хелпер существует только для того, чтобы сделать Docker-стенд детерминированным и полностью локальным.
Репозиторий предназначен только для локальных исследований в области безопасности и демонстрации портфолио.
Ограничения:
localhost и сервисах Docker-сетиcmd=Полезная нагрузка 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