
Lab Docker local para reproduzir a CVE-2026-3844, um upload arbitrário de arquivos não autenticado que leva a RCE no plugin WordPress Breeze Cache. Compara a versão vulnerável 2.4.4 com a corrigida 2.4.5 usando serviços isolados e um PoC de menor impacto.
Laboratório Docker exclusivamente local para reproduzir e comparar o comportamento da CVE-2026-3844 no plugin Breeze Cache do WordPress.
Este repositório demonstra o comportamento vulnerável no Breeze Cache 2.4.4 e o compara com o comportamento corrigido no Breeze Cache 2.4.5. O laboratório usa dois serviços WordPress isolados, um vulnerável e um corrigido, além de um servidor de payload local dentro da rede Docker.
A prova de conceito é intencionalmente de dano mínimo: não usa webshell, não expõe parâmetro de comando, não inicia reverse shell e não exige leitura de arquivos de dentro do contêiner. A prova baseia-se no comportamento HTTP observável a partir do host.
A CVE-2026-3844 afeta o plugin Breeze Cache para WordPress até a versão 2.4.4, inclusive. O caminho de código vulnerável está relacionado ao recurso de cache local de Gravatars do plugin, especificamente ao fluxo fetch_gravatar_from_remote().
Quando a opção Host Files Locally - Gravatars do Breeze está habilitada, versões vulneráveis podem buscar um arquivo remoto controlado pelo atacante e armazená-lo em um diretório de cache publicamente acessível via web. Se o arquivo buscado for PHP, ele pode ser executado pelo servidor web quando solicitado via HTTP.
Este laboratório reproduz esse comportamento localmente:
vuln: WordPress + Breeze Cache 2.4.4patched: WordPress + Breeze Cache 2.4.5payload: servidor de payload local exclusivo do Dockersrcset controladaO resultado esperado é:
http://127.0.0.1:8081 / Breeze 2.4.4 → o PHP de prova é armazenado em cache e executadohttp://127.0.0.1:8082 / Breeze 2.4.5 → o PHP de prova não é armazenado em cache/não é legível/não é executado.
├── 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
Os contêineres WordPress buscam o payload por meio da URL da rede Docker:
http://payload:9100/<payload-file>.php
O host verifica o resultado por meio de requisições HTTP normais aos serviços WordPress.
2.4.42.4.5fetch_gravatar_from_remote()inc/class-breeze-cache-cronjobs.phpbreeze-store-gravatars-locally deve estar habilitadoO comportamento vulnerável só é alcançável quando o cache local de Gravatars está habilitado. Essa opção vem desabilitada por padrão em instalações típicas, mas este laboratório a habilita intencionalmente para reproduzir o caminho de código vulnerável.
No Breeze Cache 2.4.4, o fluxo de localização de Gravatars pode extrair uma URL remota do HTML relacionado a avatares e passar essa URL para fetch_gravatar_from_remote().
A versão vulnerável não possui validação suficiente em relação ao arquivo remoto:
.phpO arquivo resultante é armazenado em:
/wp-content/cache/breeze-extra/gravatars/
Quando um arquivo PHP é salvo nesse diretório e depois solicitado por meio do Apache/PHP, o servidor o executa.
No Breeze Cache 2.4.5, o fluxo corrigido adiciona validação que impede que este payload do laboratório seja armazenado em cache como PHP executável. Na reprodução local, o mesmo gatilho funciona contra o 2.4.4, mas não expõe o marcador de prova contra o 2.4.5.
Este laboratório mantém intencionalmente o servidor de payload local em vez de usar um host de payload público.
O download_url() do WordPress e a API HTTP do WordPress rejeitam por padrão alguns hostnames Docker privados e portas não padronizadas. Scripts de exploit públicos costumam usar URLs de payload HTTPS públicas, que evitam essa restrição. Este laboratório não faz isso.
Para manter a reprodução totalmente local, o script de seed instala um pequeno helper de MU plugin local-only que:
payload e payload.local80 e 9100Este helper não modifica o código-fonte do Breeze. Tanto o serviço vulnerável quanto o corrigido usam versões reais do plugin Breeze instaladas via WP-CLI.
O helper existe apenas para tornar o laboratório Docker determinístico e exclusivamente local.
Este repositório destina-se apenas a pesquisa de segurança local e demonstração de portfólio.
Salvaguardas:
localhost e em serviços da rede Dockercmd=O payload da PoC imprime informações benignas do runtime do PHP:
CVE-2026-3844_LEAST_HARM_PHP_EXEC_PROOF_<nonce>
php_sapi=apache2handler
user=www-data
uid=33
pid=<process id>
host=<container hostname>
Isso comprova o contexto de execução de código sem disparar comandos de shell.
requestsInstale a dependência Python:
python3 -m venv .venv
source .venv/bin/activate
pip install -r poc/requirements.txt
O requirements.txt deve conter:
requests
Compile e inicie o laboratório:
docker compose down -v --remove-orphans
docker compose up -d --build
Verifique o status dos serviços:
docker compose ps
Serviços esperados:
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
Verifique os logs do seed:
docker compose logs --tail=120 vuln
docker compose logs --tail=120 patched
Linhas de log esperadas:
[seed] WordPress ready at http://localhost:8081 with Breeze 2.4.4
[seed] WordPress ready at http://localhost:8082 with Breeze 2.4.5
Verifique a instalação do 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
Verifique as versões do Breeze: