CVE-2026-94504 / 93836: Ninja Forms and WPC Bundles XSS Is Planting Hidden WordPress Admins - Floor 3.15.5 / 8.6.7

The Situation
This is not unauthenticated PHP upload. Two HIGH stored XSS bugs, disclosed 22 September 2026, are being used as the same front door for a persistence implant that hides an administrator from wp-admin. Patchstack published the campaign write-up on 6 October 2026. First observed attempt: 4 October 2026, 10:39 UTC.[1][4]
| CVE | CNA product / slug | Affected (CNA) | Wordfence patched | CNA CVSS 3.1 |
|---|---|---|---|---|
| CVE-2026-93836 | WPC Product Bundles for WooCommerce / woo-product-bundle |
≤ 8.6.6 | 8.6.7 (changelog: "Vulnerability reported by lhking from Wordfence") | 7.2 HIGH AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N |
| CVE-2026-94504 | Ninja Forms / ninja-forms |
≤ 3.15.3 | 3.15.4 | 7.2 HIGH same vector |
CNA is Wordfence on both. NVD status Deferred. CWE-79. Finders: lhking (93836), Hippolyte Quéré (Hippie) (94504). Patchstack scores the same two bugs 7.1 on the article cards. We use 7.2 as the CNA number.[1][2][3][5][6]
CISA KEV catalog version 2026.10.13 (count 1741, dateReleased 2026-10-13T19:10:43.6568Z) does not list 93836, 94504, or the sibling Ninja Forms XSS CVE-2026-90438. Newest KEV adds that day were Ivanti Connect Secure and Windows - not these plugins. Do not wait for a BOD due date.[7]
wordpress.org active_installs this morning: ninja-forms 500000, version 3.15.5 (last_updated 2026-09-28 12:10pm GMT). woo-product-bundle 30000, version 8.7.5 (last_updated 2026-10-12 5:01am GMT). Those are the API integers, not marketing copy.[8][9]
Operator floor is not 3.15.4. CVE-2026-94504 is closed in 3.15.4. CVE-2026-90438 is a different unauthenticated stored XSS in Paragraph Text (RTE) submissions, CNA affected ≤ 3.15.4, NVD published 2026-10-02T06:16:42.050, Wordfence public 1 October 2026. Changelog for 3.15.5 (28 September 2026): "strengthen sanitization of Paragraph Text (Rich Text) field submissions against stored cross-site scripting." Trac diff is 3.15.4 → 3.15.5. Take 3.15.5. On WPC, 8.6.7 is the 93836 fix; 8.7.3 later says it rebuilt bundle IDs to stop another stored XSS. Current trunk is 8.7.5. Take current, not "just past 8.6.6."[10][11][12]
What the bugs actually are
93836 / NVD, verbatim: unauthenticated stored XSS via the qty parameter through 8.6.6. A float cast during quantity validation lets a numeric-prefixed payload through; the original value is stored in order item meta under _woosb_ids and rendered later. Wordfence title: Unauthenticated Stored Cross-Site Scripting via qty. Publicly published 22 September 2026 on CVE.org (datePublished 2026-09-22T07:41:16.170Z).[2][5]
94504 / NVD, verbatim: Ninja Forms 3.15.3 stores an anonymous non-RTE textarea value and renders it without safe HTML encoding in the legacy submission editor. When an administrator opens the attacker-known direct submission URL, the script runs in the WordPress admin origin. Wordfence patched version 3.15.4. Changelog 3.15.4 (21 September 2026): "strengthen output escaping in admin submission edit screen; responsibly reported by Venkateswara Reddy Challa" - that credit line is the 3.15.4 changelog; the CVE-2026-94504 finder on CVE.org is Hippolyte Quéré. We are not collapsing those two names into one report.[1][3][6][11]
CNA vector is UI:N on both. Patchstack's campaign still describes the payoff as JavaScript running in a logged-in administrator's browser when they open a WooCommerce order or a Ninja Forms submission. Those two statements both stand: Wordfence scored UI:N; Patchstack describes admin viewing as the implant trigger. We did not re-score CVSS.[1][4]
We are not publishing the injection strings Patchstack captured.
Exploitation - Patchstack, not us
Patchstack, 6 October 2026 article. Two plugins, one second stage.
- 4 Oct 2026 - 93836 / WPC. Payload via
woosb_ids[…][qty]. Earliest request 10:39 UTC. Source IPs they published:204.8.96.109,147.90.235.22,90.184.10.74,94.16.115.121. - 5 Oct 2026 - 94504 / Ninja Forms. Same
https://imgcdn1.com/fz/x.jsvia/wp-admin/admin-ajax.phpaction=nf_ajax_submit. Source IP they published:43.250.53.42.
They call volume limited as of that article and say two confirmed vectors is not a ceiling. Four of five IPs are described as Tor exits; they say blocking those addresses is not a durable mitigation. Domain imgcdn1.com registered 1 October 2026, Cloudflare NS hazel.ns.cloudflare.com on 2 Oct, exploitation two days later. Both CVEs had been public since 22 September - about ten days before the domain.[4]
Second stage they analysed (their hashes, not ours):
- Browser implant
x.js(19,378 bytes). SHA-256 they list:af803bc822cf9596b1f1785e1d59642f91f6fbc21f8e9943feefa19a6df8c2a4. - C2
https://imgcdn1.com/fz/c.php(xa=check,xa=pkg,xa=admin_creds). - Malicious plugin slug
wp-smart-thumbnails, identity "WP Smart Thumbnails" 1.2.4 by "MediaPress Labs". Dropperwp-smart-thumbnails.phpSHA-256ccc95113334357c2a3671aae12043bff00020858cec115f7e724fe43e9f1fc24. Persistence installeremer-run.phpSHA-256ed00234ad2b67dbbc9073e8c711b18b7d39e0a5255b6159189f75cf2ed99cfb9. - MU-plugins:
wp-content/mu-plugins/class-wp-query-<8 hex>.phpandclass-wp-token-validate.php(per-site XOR+gzdeflate; no stable hash). - Options:
fz_emer_done_v1,fz_emer_login_tokens. - Magic login:
/wp-login.php?_wplogin=<token>- Patchstack says the token authenticates as the oldest existing administrator, not the hidden one. - Webshell title string they recovered:
Moon, tell me if I could. Direct request only; invertedABSPATHguard so the plugin is inert while WordPress loads it.
Four persistence paths they name: visible admin via user-new.php; hidden admin filtered out of Users; magic login URL; unauthenticated file manager in the dropper. Removing Ninja Forms / WPC / even wp-smart-thumbnails does not remove the last three.[4]
The Hacker News 12 October Bricksforge piece mentions this campaign in passing. That is secondary. Yesterday's Bricksforge post (CVE-2026-85097) is a different plugin and a different class (unauth file upload). Do not patch Bricksforge and skip this hunt.[13]
Hunt the fleet - versions first, then disks and the database
# slugs, not marketing names
find /home /var/www /srv -path '*/wp-content/plugins/ninja-forms' -type d 2>/dev/null
find /home /var/www /srv -path '*/wp-content/plugins/woo-product-bundle' -type d 2>/dev/null
# headers, no PHP bootstrap
grep -hE '^[[:space:]]*\*?[[:space:]]*Version:' \
/home/*/public_html/wp-content/plugins/ninja-forms/ninja-forms.php \
/home/*/public_html/wp-content/plugins/woo-product-bundle/*.php \
2>/dev/null
# per-site when wp-cli is on the account
wp plugin get ninja-forms --field=version --skip-plugins --skip-themes
wp plugin get woo-product-bundle --field=version --skip-plugins --skip-themes
ninja-forms ≤ 3.15.3 is 94504. 3.15.4 still has 90438. Floor: 3.15.5.
woo-product-bundle ≤ 8.6.6 is 93836. Floor for that CVE: 8.6.7. Prefer 8.7.5.
wp plugin update ninja-forms --skip-plugins --skip-themes
wp plugin update woo-product-bundle --skip-plugins --skip-themes
Both are on wordpress.org; wp plugin update is the right channel.
If a site ran a vulnerable build on or after 4 Oct 2026 and an administrator opened orders or form submissions, treat it as possibly compromised until you have looked outside wp-admin Users. Patchstack: the hidden account is filtered with pre_user_query / login__not_in / decremented role counts. The Plugins screen will not list MU-plugins. mtime is a lie - they stamp dropped files to the oldest time in the WordPress root.[4]
# implant slug + MU-plugin names Patchstack published
find /home /var/www /srv -path '*/wp-content/plugins/wp-smart-thumbnails' -type d 2>/dev/null
find /home /var/www /srv -path '*/wp-content/mu-plugins/class-wp-token-validate.php' 2>/dev/null
find /home /var/www /srv -path '*/wp-content/mu-plugins/class-wp-query-*.php' 2>/dev/null
-- replace wp_ with the site prefix
SELECT u.ID, u.user_login, u.user_email, u.user_registered
FROM wp_users u
JOIN wp_usermeta m ON m.user_id = u.ID
WHERE m.meta_key = 'wp_capabilities'
AND m.meta_value LIKE '%administrator%';
SELECT option_name FROM wp_options
WHERE option_name IN ('fz_emer_done_v1', 'fz_emer_login_tokens');
Compare that admin list to Users → All Users. An account in SQL and not in the UI is the MU-plugin hiding it. Patchstack extra signals: @wordpress.org on a local account; logins like support / updater / maintenance / backup. Presence of fz_emer_login_tokens means a magic URL is live. Deleting the options without removing the MU-plugins is not enough - they say a fresh token can be issued.[4]
Logs: imgcdn1.com, /fz/x.js, /fz/c.php, woosb_ids, nf_ajax_submit, _wplogin= on wp-login.php, direct hits on wp-smart-thumbnails.php. Do not close on the five IPs.
If you confirm the implant: remove the unauthorized users from SQL, delete the MU-plugins and wp-smart-thumbnails, drop those two options, rotate the oldest administrator's password (the magic URL authenticates as them), rotate salts in wp-config.php, rotate DB/FTP/SFTP/API keys that lived on disk. Then patch to the floors above. Removing the XSS plugin alone does not unwind this.
Honesty / What We Could Not Verify
- We did not exploit this. No XSS payload was submitted. No implant ZIP was downloaded or unpacked. Hashes, file sizes, stream-wrapper name, and webshell title are Patchstack's, quoted as telemetry, not reproduced here.
- Not on CISA KEV as of catalog 2026.10.13 / count 1741. We re-read that JSON this morning. Newest
dateAdded2026-10-13 is CVE-2026-104935 (Ivanti) and CVE-2026-96951 (Windows), not WordPress.[7] - CVSS 7.2 vs 7.1. CNA/Wordfence/NVD is 7.2. Patchstack article cards show 7.1. No CVSS v4 object on the NVD records we pulled.[1][2][4]
- UI:N vs "admin opens the submission." CNA vector is UI:N. Patchstack's implant story requires an administrator to view stored data. We are not "fixing" Wordfence's score.
- Volume. Patchstack, 6 Oct: limited in their telemetry; two plugins confirmed, not a ceiling. We have no later public volume number as of this morning.
- 3.15.4 vs 3.15.5. 94504's patched version is 3.15.4. 90438's affected range includes 3.15.4. wordpress.org current is 3.15.5. We did not prove 90438 is in this campaign; we are still telling operators not to stop at 3.15.4.[10][11]
- 8.6.7 vs 8.7.3. 8.6.7 is the lhking/Wordfence line. 8.7.3 is a later stored-XSS changelog sentence about bundle IDs. Current is 8.7.5. We did not bisect 8.6.7-8.7.2.[12]
- Table prefix. Hunt SQL uses
wp_. Real prefixes differ.wp_capabilitiesis actually{prefix}capabilities. - Finder vs changelog credit on 3.15.4. CVE-2026-94504 finder is Hippolyte Quéré. 3.15.4 changelog names Venkateswara Reddy Challa on the escaping work. Separate Wordfence records exist for other Ninja Forms XSS CVEs in the same week (95515, 92438, 102385). We did not map every one of those to a campaign hit.[3][6][11]
- This lab did not install Ninja Forms or WPC Product Bundles.
What this is not
- Not CVE-2026-85097 (Bricksforge ≤ 3.1.8.9 unauth PHP upload, Patchstack ITW 7 Oct). Different slug (
bricksforge). Yesterday's post. - Not CVE-2026-87902 (WordPress core page-template LFI, KEV 25 Sep 2026). Core, not these plugins.
- Not a cPanel / Plesk / LiteSpeed / Proxmox / CloudLinux KEV. No new named-stack KEV since catalog 2026.10.08; 13 Oct adds were Ivanti and Windows.[7]
- Not "XSS is low, skip it." The CVSS is 7.2 because C/I are Low. The campaign Patchstack documented turns that XSS into hidden admin + magic login + unauth file manager. Hunt as persistence, not as a forms ticket.
Sources
[1] https://nvd.nist.gov/vuln/detail/CVE-2026-94504 - NVD CVE-2026-94504 [2] https://nvd.nist.gov/vuln/detail/CVE-2026-93836 - NVD CVE-2026-93836 [3] https://www.wordfence.com/threat-intel/vulnerabilities/id/c599a562-5218-4b37-bcf7-0e82008a4e68?source=cve - Wordfence CVE-2026-94504 [4] https://patchstack.com/articles/four-ways-back-in-the-wordpress-xss-campaign-that-hides-its-own-admin-account/ - Patchstack campaign, 6 Oct 2026 [5] https://www.wordfence.com/threat-intel/vulnerabilities/id/fc620054-00ed-4c2e-9448-b40ae28efff3?source=cve - Wordfence CVE-2026-93836 [6] https://www.cve.org/CVERecord?id=CVE-2026-94504 - CVE.org CVE-2026-94504 [7] https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json - CISA KEV JSON [8] https://api.wordpress.org/plugins/info/1.2/?action=plugin_information&request%5Bslug%5D=ninja-forms - WordPress.org plugin API ninja-forms [9] https://api.wordpress.org/plugins/info/1.2/?action=plugin_information&request%5Bslug%5D=woo-product-bundle - WordPress.org plugin API woo-product-bundle [10] https://nvd.nist.gov/vuln/detail/CVE-2026-90438 - NVD CVE-2026-90438 (Ninja Forms ≤ 3.15.4 RTE XSS) [11] https://plugins.svn.wordpress.org/ninja-forms/tags/3.15.5/readme.txt - Ninja Forms 3.15.5 changelog [12] https://plugins.svn.wordpress.org/woo-product-bundle/trunk/readme.txt - WPC Product Bundles changelog [13] https://thehackernews.com/2026/10/attackers-exploit-cvss-100-bricksforge.html - THN (secondary; mentions this campaign next to Bricksforge) [14] https://cveawg.mitre.org/api/cve/CVE-2026-94504 - CVE AWG JSON 94504 [15] https://cveawg.mitre.org/api/cve/CVE-2026-93836 - CVE AWG JSON 93836