Skip to content
HackIndex logo

HackIndex

WordPress Enumeration

5 min read Mar 30, 2026

WordPress enumeration maps the installed version, active plugins, themes, and user accounts. Outdated plugins are the most common path to exploitation on WordPress targets. Run this after tech fingerprinting confirms WordPress. Vulnerabilities discovered here feed into WordPress exploitation.

Confirm WordPress and Version

Before running wpscan, quickly confirm the install and get a version hint from the generator meta tag or readme:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/ | grep -i 'wordpress\|wp-content\|wp-includes'
<meta name="generator" content="WordPress 5.9" />
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure TLS connections, skipping certificate verification.
http://$TARGET_IP:$PORT/ Target URL built from variable host IP and port number.
-i Case-insensitive pattern matching in grep.
'wordpress\|wp-content\|wp-includes' Grep pattern matching common WordPress path/keyword indicators.
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/readme.html | grep -i 'version'
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure SSL connections, skipping certificate verification.
http://$TARGET_IP:$PORT/readme.html Target URL with variable host IP and port to fetch readme.html.
-i Case-insensitive pattern matching in grep.
'version' Pattern to search for version strings in the fetched content.

wpscan Full Enumeration

wpscan is the primary tool. A full passive enumeration of plugins, themes, and users without authentication:

┌──(kali㉿kali)-[~]
└─$ wpscan --url http://$TARGET_IP:$PORT/ --enumerate p,t,u --plugins-detection passive
Explain command
--url Target URL to scan.
http://$TARGET_IP:$PORT/ Target host IP and port as a URL placeholder.
--enumerate Specifies enumeration types to perform.
p,t,u Enumerate plugins (p), themes (t), and users (u).
--plugins-detection Sets the detection mode for plugins.
passive Use passive detection to avoid sending extra requests.

Aggressive detection hits more plugins but generates significantly more traffic:

┌──(kali㉿kali)-[~]
└─$ wpscan --url http://$TARGET_IP:$PORT/ --enumerate p,t,u --plugins-detection aggressive
Explain command
--url http://$TARGET_IP:$PORT/ Target WordPress site URL with variable host and port.
--enumerate p,t,u Enumerate plugins (p), themes (t), and users (u).
--plugins-detection aggressive Use aggressive mode to detect plugins via extensive requests.

With a WPScan API token, vulnerability data is included inline with results:

┌──(kali㉿kali)-[~]
└─$ wpscan --url http://$TARGET_IP:$PORT/ --enumerate p,t,u --api-token YOUR_TOKEN --plugins-detection aggressive
Explain command
--url http://$TARGET_IP:$PORT/ Target WordPress site URL with variable IP and port.
--enumerate p,t,u Enumerate plugins (p), themes (t), and users (u).
--api-token YOUR_TOKEN WPScan API token for vulnerability database lookups.
--plugins-detection aggressive Use aggressive mode for thorough plugin detection.

User Enumeration

WordPress leaks usernames through the author archive and REST API by default:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/?author=1 -I | grep -i location
Location: http://10.10.10.50/author/admin/
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure SSL connections, skipping certificate verification.
http://$TARGET_IP:$PORT/?author=1 Target URL with host, port, and author enumeration query parameter.
-I Send a HEAD request, retrieving only response headers.
-i Case-insensitive matching for grep pattern.
location Filter output to show only the Location redirect header.
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/wp-json/wp/v2/users | python3 -m json.tool
[{"id":1,"name":"admin","slug":"admin"},{"id":2,"name":"editor","slug":"editor"}]
Explain command
-s Silent mode; suppresses progress and error messages.
-k Allows insecure TLS connections, skipping certificate verification.
http://$TARGET_IP:$PORT/wp-json/wp/v2/users Target URL with variable host and port for WordPress REST API users endpoint.
-m json.tool Runs Python's json.tool module to pretty-print JSON output.

Enumerate IDs sequentially to collect all users:

┌──(kali㉿kali)-[~]
└─$ for i in $(seq 1 10); do curl -sk http://$TARGET_IP:$PORT/?author=$i -I | grep -i location; done
Explain command
$(seq 1 10) Generates a sequence of integers from 1 to 10 for iteration.
-s Silent mode; suppresses progress meter and error messages.
-k Allows insecure SSL/TLS connections by skipping certificate verification.
http://$TARGET_IP:$PORT/?author=$i Target URL with dynamic IP, port, and author ID substituted per iteration.
-I Sends a HEAD request and fetches only the HTTP response headers.
-i Makes the grep pattern match case-insensitive.
location Filters output to show only the HTTP Location redirect header.

Plugin and Theme Version Checks

Once you have a plugin list, check individual plugin readmes for version disclosure:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/wp-content/plugins/PLUGIN_NAME/readme.txt | grep -i 'stable tag\|version'
Stable tag: 3.2.1
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure TLS connections, skipping certificate verification.
http://$TARGET_IP:$PORT/wp-content/plugins/PLUGIN_NAME/readme.txt Target URL with variable host, port, and plugin name placeholders.
-i Case-insensitive pattern matching in grep.
'stable tag\|version' Grep pattern matching lines containing 'stable tag' or 'version'.

Exposed Files and Configuration

Check for commonly exposed WordPress files that reveal configuration or enable further enumeration:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/wp-config.php.bak
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/wp-config.php~
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/.wp-config.php.swp
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure TLS connections; skip certificate verification.
$TARGET_IP:$PORT Placeholder for target host IP and port number.
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/wp-cron.php
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure SSL connections by skipping certificate verification.
http://$TARGET_IP:$PORT/wp-cron.php Target URL with variable host IP, port, and WordPress cron endpoint.

XML-RPC Check

XML-RPC is a legacy interface that enables brute force amplification and can be abused for credential stuffing. Check if it's active:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/xmlrpc.php -d "<methodCall><methodName>system.listMethods</methodName></methodCall>"
<value><string>system.multicall</string></value>
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure SSL connections by skipping certificate verification.
http://$TARGET_IP:$PORT/xmlrpc.php Target URL with variable host and port pointing to WordPress XML-RPC endpoint.
-d Send specified data as HTTP POST request body.
<methodCall><methodName>system.listMethods</methodName></methodCall> XML-RPC payload requesting a list of all available server methods.

system.multicall being available confirms XML-RPC is active and allows brute force amplification — multiple login attempts per HTTP request. This significantly speeds up credential attacks against the WordPress login.

Take enumeration results to WordPress exploitation for credential attacks, plugin exploitation, and theme editor abuse.

References