| name | cve-reversing |
| description | Reverse-engineer a WordPress plugin/theme CVE from its patch and build a working proof-of-concept. Use whenever reversing a WordPress vulnerability, analyzing a plugin CVE, building a PoC from a patch diff, or producing a bug-bounty writeup + nuclei template for a disclosed WordPress bug. Downloads the vulnerable and patched versions, diffs them, identifies the bug, and writes the repo deliverables.
|
| allowed-tools | Bash, WebFetch, Read, Write |
Reversing a WordPress CVE from its patch
The patch is the inverse of the bug. Given a disclosed, already-patched WordPress
vulnerability, this skill downloads the vulnerable and fixed versions, diffs the code,
reads the fix to identify the vulnerability, builds a working PoC, and produces a
complete bug-bounty package in the repo.
Scope: only publicly disclosed, already-patched vulnerabilities, for learning to
read patches faster and for defensive detection. PoCs are written to be verified in a
local lab — not turnkey mass-exploitation scripts.
Step 1 — Pin down the target (from the Patchstack CVE page)
- Open the CVE's Patchstack detail page
(e.g.
https://patchstack.com/database/wordpress/plugin/<slug>/vulnerability/...).
- Find the affected software link. Follow the one that points to wordpress.org
(
https://wordpress.org/plugins/<slug>/). Ignore CodeCanyon / Envato / "premium"
links — those are paid and not freely downloadable. If the plugin has no free
wordpress.org listing (premium-only), skip this CVE.
- On the wordpress.org page, confirm the plugin is still available — not marked
"closed" or removed. Closed/removed plugins usually can't be downloaded; if so, note
it and skip.
- Record:
- the slug (from the
/plugins/<slug>/ URL),
- the vulnerable version (highest affected, e.g. from "<= 3.15.0.5" →
3.15.0.5),
- the fixed version (Patchstack's "fixed in", e.g.
3.15.0.6).
Step 2 — Download + diff (built-in shell tools, no scripts)
WordPress.org serves any version at
https://downloads.wordpress.org/plugin/<slug>.<version>.zip — the page's download
button is just the latest, so swap the version in the URL to grab a specific one.
Download the vulnerable version and the fixed version, then diff:
mkdir -p /tmp/cvediff && cd /tmp/cvediff && rm -rf vuln fixed
curl -fsSL -o vuln.zip "https://downloads.wordpress.org/plugin/<slug>.<vulnerable_version>.zip"
curl -fsSL -o fixed.zip "https://downloads.wordpress.org/plugin/<slug>.<fixed_version>.zip"
unzip -oq vuln.zip -d vuln && unzip -oq fixed.zip -d fixed
diff -ruN vuln fixed > changes.diff
cat changes.diff
curl -f fails loudly if a version zip 404s (wrong tag, or version pulled). When reading
changes.diff, focus on the plugin's own PHP (.php/.inc); ignore vendor/,
node_modules/, languages/, minified .min.js, and whitespace-only edits. If a tag
won't download, check the plugin's Trac/SVN
(https://plugins.trac.wordpress.org/log/<slug>/) for the exact version tags.
Step 3 — Identify the vulnerability from the diff
Read the added/changed lines. The fix tells you the bug:
- Added
current_user_can() / is_user_logged_in() / capability check → Missing Authorization / Broken Access Control (CWE-862).
- Added
wp_verify_nonce() / check_admin_referer() / check_ajax_referer() → CSRF (CWE-352).
$wpdb->prepare() replacing string-concatenated SQL → SQL Injection (CWE-89).
- Added
esc_html/esc_attr/esc_url/wp_kses on output → XSS (CWE-79).
- Added
sanitize_*, absint, type casts, allow-lists on input → injection/traversal depending on the sink.
- Guarded/removed
unserialize, eval, dynamic include, file_get_contents(url),
move_uploaded_file, call_user_func → object injection / RCE / LFI / SSRF / upload.
wp_ajax_nopriv_* handler changes → exposure/privilege change.
Trace the tainted input ($_GET/$_POST/$_REQUEST/$_FILES/$_COOKIE, REST args, AJAX
actions) from where it enters to the sink the patch now guards. The gap is the vuln.
Note the exact file, function, AJAX action / REST route, and parameter.
Step 4 — Build a working PoC (from the diff)
Construct the request that reaches the now-guarded sink in the vulnerable version:
- the HTTP method + endpoint (e.g.
admin-ajax.php?action=<name>, a REST route, a page),
- the privilege needed (unauth / subscriber+ / etc.),
- the parameter that carries the payload + an example payload that proves impact
(e.g. a boolean/time-based SQLi probe, a benign XSS marker, a controlled SSRF callback).
Keep it lab-grade and minimal — enough to confirm, not to weaponize.
Step 5 — Write the deliverables into the repo
For the CVE folder <YEAR>/<CVE_ID>/ (fallback <slug>-<version>/ if no CVE), write:
-
README.md — summary + root-cause analysis (file/function, source→sink, the exact
lines the patch added), vuln class + CWE, affected/fixed versions, who can exploit it.
-
report.md — a bug-bounty step-by-step report: how a hunter uses this finding —
set up a local lab with the vulnerable version, where the entry point is, the exact
steps to trigger it, expected vs. patched behavior, severity/impact, and remediation.
Written like a submittable report.
-
poc.md — the working PoC, including:
- a copy-paste
curl command that reproduces it against a local install, and
- any additional steps the user may need (auth/login to get a cookie, required
plugin settings, seeding data, headers like
X-Forwarded-For, etc.).
-
nuclei.yaml — a nuclei template that detects this across bug-bounty programs:
correct id, info (name, author, severity from CVSS, tags, reference to the
Patchstack URL + CVE), an http request hitting the vulnerable endpoint, and
matchers keyed on a reliable signal (response string, status, time delay for blind
SQLi). Make it safe and specific — no destructive payloads. Validate structure with
nuclei -validate -t nuclei.yaml if nuclei is available.
Also commit changes.diff (the raw diff from step 2) into the folder for reference.
Rules
- Ground every claim in the diff. If the real fix is in a bumped
vendor/ dependency
the diff filtered out, say so and flag low confidence.
- Don't fabricate endpoints/params you can't see — derive them from the changed code.
- Nuclei templates and PoCs are for authorized testing / local labs only.