What Is WPScan?
WPScan is a free, open-source security scanner specifically designed for WordPress. It checks WordPress installations for known vulnerabilities in the core software, plugins, and themes. It can also enumerate users, test for weak passwords, and identify security misconfigurations. WPScan is used by security professionals, penetration testers, and WordPress administrators to audit their sites and identify issues before attackers do.
WordPress powers over 40% of all websites on the internet, making it the most targeted content management system. The WordPress core is generally well-maintained and quickly patched, but the ecosystem of 60,000+ plugins and thousands of themes creates a massive attack surface. Many software vulnerabilities exploited in WordPress attacks are in outdated plugins that site administrators have not updated.
Installing WPScan
Method 1: Ruby Gem (Recommended)
WPScan is written in Ruby and distributed as a gem:
# Install Ruby and dependencies (Ubuntu/Debian)
sudo apt install ruby ruby-dev build-essential libcurl4-openssl-dev zlib1g-dev -y
# Install WPScan
sudo gem install wpscan
# Verify installation
wpscan --version
On CentOS/RHEL:
sudo yum install ruby ruby-devel gcc make libcurl-devel -y
sudo gem install wpscan
Method 2: Docker
Docker provides the simplest installation with no dependency management:
# Pull the official WPScan Docker image
docker pull wpscanteam/wpscan
# Run a scan
docker run -it --rm wpscanteam/wpscan --url https://example.com
# With API token
docker run -it --rm wpscanteam/wpscan --url https://example.com --api-token YOUR_TOKEN
Method 3: Kali Linux
WPScan is pre-installed on Kali Linux. Update it to the latest version:
sudo apt update && sudo apt install wpscan -y
# Or update via gem
sudo gem update wpscan
API Token Setup
WPScan uses the WPVulnDB API to look up known vulnerabilities for the WordPress version, plugins, and themes it detects. Without an API token, WPScan will still scan but will not report vulnerability information.
To get a free API token:
- Register at
https://wpscan.com/register - The free plan provides 25 API requests per day (sufficient for scanning a few sites daily)
- Copy your API token from the dashboard
Configure the token so you do not need to specify it on every scan:
# Create WPScan config directory
mkdir -p ~/.wpscan
# Save the token
echo "cli_options:" > ~/.wpscan/scan.yml
echo " api_token: YOUR_API_TOKEN_HERE" >> ~/.wpscan/scan.yml
Alternatively, pass it on the command line:
wpscan --url https://example.com --api-token YOUR_API_TOKEN_HERE
Basic Scanning
A basic WPScan command detects the WordPress version, active theme, and known vulnerabilities:
# Basic scan
wpscan --url https://example.com
# Scan with verbose output
wpscan --url https://example.com -v
# Scan a site using HTTP (not HTTPS)
wpscan --url http://example.com
# Scan a WordPress installation in a subdirectory
wpscan --url https://example.com/blog/
A basic scan reveals:
- WordPress version and whether it is outdated
- Active theme name and version
- Interesting headers (server, X-Powered-By, etc.)
- XML-RPC availability (common attack vector)
- WordPress readme.html (reveals version information)
- Upload directory listing (potential information disclosure)
- Known vulnerabilities (with API token)
Enumerating Users
User enumeration discovers valid WordPress usernames, which can then be used in brute force attacks. WPScan uses multiple techniques: author archives, REST API, login error messages, and RSS feeds.
# Enumerate users
wpscan --url https://example.com -e u
# Enumerate with a specific range of user IDs
wpscan --url https://example.com -e u1-100
Example output:
[+] Enumerating Users (via Passive and Aggressive Methods)
Brute Forcing Author IDs - Time: 00:00:02
[i] User(s) Identified:
[+] admin
| Found By: Author Posts - Display Name
[+] editor
| Found By: Author Id Brute Forcing - Author Pattern
[+] john.doe
| Found By: Rss Generator
Remediation: Disable author archives if they are not needed, restrict the WordPress REST API user endpoint, and use a WAF to block enumeration attempts.
Enumerating Plugins
Plugin vulnerabilities are the number one attack vector for WordPress sites. WPScan checks installed plugins against its vulnerability database:
# Enumerate all plugins (aggressive, checks ~100,000 known plugins)
wpscan --url https://example.com -e ap
# Enumerate only vulnerable plugins (faster)
wpscan --url https://example.com -e vp
# Specify detection mode
wpscan --url https://example.com -e ap --plugins-detection aggressive
Detection modes:
- passive: Checks page source for plugin references. Fast but may miss plugins.
- mixed (default): Combines passive checks with active probing of the most popular plugins.
- aggressive: Actively checks for every known plugin by requesting its directory. Thorough but slow and generates significant traffic.
Enumerating Themes
# Enumerate all themes
wpscan --url https://example.com -e at
# Enumerate only vulnerable themes
wpscan --url https://example.com -e vt
While the active theme is the primary concern, inactive themes that remain installed can also contain vulnerabilities. Delete any themes that are not in use.
Brute Force Password Testing
WPScan can test WordPress login credentials against a password list. This should only be done on systems you own or have explicit authorization to test.
# Brute force with a password list
wpscan --url https://example.com --passwords /usr/share/wordlists/rockyou.txt --usernames admin
# Brute force with multiple usernames
wpscan --url https://example.com --passwords passwords.txt --usernames admin,editor,john.doe
# Limit threads to avoid account lockout
wpscan --url https://example.com --passwords passwords.txt --usernames admin --max-threads 2
# Use XML-RPC multicall for faster brute force
wpscan --url https://example.com --passwords passwords.txt --usernames admin --password-attack xmlrpc-multicall
WPScan supports multiple brute force methods:
- wp-login (default): Standard login form submission. Slower but most reliable.
- xmlrpc: Uses the XML-RPC interface. Can be faster and may bypass some login protections.
- xmlrpc-multicall: Uses XML-RPC system.multicall to test multiple passwords in a single request. Significantly faster but may be blocked by WAFs.
Output Formats
# Default output (terminal)
wpscan --url https://example.com
# JSON output (for parsing and automation)
wpscan --url https://example.com -f json -o results.json
# CLI output to file
wpscan --url https://example.com -o results.txt
JSON output is structured and includes detailed vulnerability information, CVE numbers, and reference URLs — ideal for integration with other security tools.
Integrating WPScan into CI/CD
Automated scanning ensures that WordPress security is checked regularly, not just when someone remembers to run a manual scan:
Cron Job (Simple Automated Scanning)
# /etc/cron.d/wpscan-daily
0 3 * * * root wpscan --url https://example.com -e vp,vt --api-token TOKEN -f json -o /var/log/wpscan/$(date +\%Y\%m\%d).json 2>&1
CI Pipeline Integration
# .gitlab-ci.yml example
security_scan:
image: wpscanteam/wpscan
script:
- wpscan --url $WORDPRESS_URL -e vp,vt --api-token $WPSCAN_TOKEN -f json -o results.json
- cat results.json | python3 -c "import sys,json; data=json.load(sys.stdin); sys.exit(1 if any(v.get('vulnerabilities') for v in data.get('plugins',{}).values()) else 0)"
artifacts:
paths:
- results.json
only:
- schedules
The Python one-liner checks whether any detected plugins have known vulnerabilities and fails the pipeline if they do, forcing remediation before deployment.
Common Findings and Remediation
Outdated WordPress Core
Update immediately. WordPress core updates are generally safe and well-tested. Enable automatic minor version updates (enabled by default since WordPress 3.7).
Vulnerable Plugins
Update to the latest version. If no patch is available, disable and delete the plugin. Find an alternative that is actively maintained. Check the plugin's last update date — plugins not updated in over a year are risky.
XML-RPC Enabled
XML-RPC enables brute force amplification (multiple login attempts per request) and DDoS via pingback. Disable it if not needed:
# In .htaccess
<Files xmlrpc.php>
Require all denied
</Files>
# Or via a plugin filter in functions.php
add_filter('xmlrpc_enabled', '__return_false');
User Enumeration Possible
Block author archive scanning and REST API user endpoints with a WAF or plugin. Use non-obvious usernames (never "admin").
Directory Listing Enabled
Add Options -Indexes to your .htaccess or Nginx configuration to prevent directory browsing.
Debug Mode Enabled
Ensure WP_DEBUG is set to false in wp-config.php on production sites. Debug output can reveal sensitive path information and PHP errors.
Protect Your WordPress Sites
WPScan identifies the vulnerabilities; closing them requires timely updates, secure configuration, and layered defenses. A web application firewall provides real-time protection against exploitation of known and unknown WordPress vulnerabilities, brute force attacks, and automated scanning tools. Explore NOC.org's WAF plans for always-on WordPress protection.