wpscan.md (16711B)
1 --- 2 title: "WPScan" 3 description: "WPScan WordPress enumeration: plugins/themes/users, vuln API tokens and password attacks." 4 category: enumeration 5 tags: [enumeration, web, wordpress] 6 tools: [WPScan] 7 difficulty: intermediate 8 updated: "2026-08-09" 9 source: "vault:Enumeration/WPScan.md" 10 --- 11 12 # WPScan 13 14 WordPress security scanner. Enumerates core version, plugins, themes, users and other components, and (with an API token) reports known vulnerabilities. Pre-installed on Kali, Parrot, BlackArch, etc. 15 16 ## Basic Scanning 17 18 Initial WordPress scan with default enumeration. 19 20 ```bash 21 wpscan --url https://target.com 22 wpscan --url https://target.com --api-token YOUR_TOKEN 23 wpscan --url https://target.com --api-token YOUR_TOKEN --no-update 24 ``` 25 26 **Key options:** 27 - `--url` (required): Target WordPress URL 28 - `--api-token TOKEN`: WPScan API token for vulnerability data (25 free requests/day) 29 - `--no-update`: Skip database update check at scan start 30 - `--force`: Ignore robots.txt disallow rules 31 - `--verbose` / `-v`: Debug output 32 - `--no-banner`: Suppress banner 33 - `--random-user-agent` / `--rua`: Randomize User-Agent 34 - `--disable-tls-checks`: Ignore TLS/SSL errors (lab/testing only) 35 36 ```bash 37 # Basic scan with API token 38 wpscan --url https://example.com --api-token abcd1234efgh5678 39 40 # Scan without updating database (faster) 41 wpscan --url https://example.com --api-token abcd1234efgh5678 --no-update 42 43 # Force scan even if robots.txt disallows 44 wpscan --url https://example.com --force 45 46 # Use environment variable for API token 47 export WPSCAN_API_TOKEN=abcd1234efgh5678 48 wpscan --url https://example.com 49 ``` 50 51 Default enumeration runs: vulnerable plugins (`vp`), vulnerable themes (`vt`), timthumbs (`tt`), config backups (`cb`), database exports (`dbe`), users (`u1-10`), media (`m1-10`). Vulnerabilities are only shown if an API token is provided. Output colours: green = low, yellow = medium, red = high/critical. 52 53 > **Note — Common errors.** `does not seem to be running WordPress` → try `--random-user-agent` or `--disable-tls-checks`. `403`/timeout on DB update → firewall blocking `data.wpscan.org`. No vulns shown → token missing or daily limit (25) exceeded. 54 55 **OPSEC:** default User-Agent `WPScan vX.X.X (...)` is logged; default scans generate 50-200+ HTTP requests (many 404s); rapid `wp-content/plugins/*` enumeration may trip IDS/IPS. 56 57 ## Plugin Enumeration 58 59 Enumerate installed plugins (popular, all, or vulnerable only). 60 61 ```bash 62 wpscan --url https://target.com -e vp # vulnerable plugins only (default) 63 wpscan --url https://target.com -e p # popular plugins (~6000 in DB) 64 wpscan --url https://target.com -e ap # ALL plugins (aggressive, slow) 65 wpscan --url https://target.com -e vp,ap --plugins-detection mixed 66 ``` 67 68 **Options:** 69 - `--plugins-detection MODE`: passive (default), mixed, aggressive 70 - `--plugins-version-detection MODE`: mixed (default), passive, aggressive 71 - `--plugins-list FILE`: Custom plugin list to check 72 - `--exclude-content-based 'REGEX'`: Filter false positives (use when 100+ plugins detected) 73 74 ```bash 75 # Enumerate vulnerable plugins only (default) 76 wpscan --url https://example.com -e vp --api-token TOKEN 77 78 # Enumerate all plugins aggressively (noisy) 79 wpscan --url https://example.com -e ap --plugins-detection aggressive --plugins-version-detection aggressive 80 81 # Combine with other enumerations 82 wpscan --url https://example.com -e vp,u1-20 --api-token TOKEN 83 84 # Filter false positives when 100+ plugins detected 85 wpscan --url https://example.com -e ap --exclude-content-based 'Error 404' 86 87 # Stealthy plugin enumeration 88 wpscan --url https://example.com -e p --plugins-detection passive --random-user-agent --throttle 2000 89 ``` 90 91 Detection modes: **passive** checks `readme.txt`/`changelog.txt` (~1-3 req/plugin, lowest noise); **mixed** adds Last-Modified header checks (~2-5 req/plugin); **aggressive** checks multiple version files (10+ req/plugin, many 404s). A full `-e ap` scan can generate tens of thousands of requests; WAFs may block aggressive enumeration ("no plugins found"). 92 93 ## Theme Enumeration 94 95 ```bash 96 wpscan --url https://target.com -e vt # vulnerable themes only (default) 97 wpscan --url https://target.com -e t # popular themes (~2000 in DB) 98 wpscan --url https://target.com -e at # ALL themes (aggressive) 99 wpscan --url https://target.com -e vt,at --themes-detection mixed 100 ``` 101 102 **Options:** `--themes-detection MODE` (passive default), `--themes-version-detection MODE`, `--themes-list FILE`. 103 104 ```bash 105 # Popular themes with mixed detection 106 wpscan --url https://example.com -e t --themes-detection mixed 107 108 # Stealthy theme enumeration 109 wpscan --url https://example.com -e t --themes-detection passive --random-user-agent 110 111 # Combine theme and plugin enumeration 112 wpscan --url https://example.com -e vt,vp,u --api-token TOKEN 113 ``` 114 115 The active theme is usually detected automatically in a basic scan; inactive themes require `-e t`/`-e at`. Enumeration pattern: `wp-content/themes/THEME/style.css`, `readme.txt`. 116 117 ## User Enumeration 118 119 ```bash 120 wpscan --url https://target.com -e u # default range 1-10 121 wpscan --url https://target.com -e u1-100 122 wpscan --url https://target.com -e u1-5,10,15-20 123 wpscan --url https://target.com -e u --users-detection mixed 124 ``` 125 126 **Options:** `--users-detection MODE` (passive default), `--users-list FILE`. 127 128 ```bash 129 # Enumerate specific users 130 wpscan --url https://example.com -e u1,2,5,10 131 132 # Stealthy user enumeration with throttling 133 wpscan --url https://example.com -e u1-20 --users-detection passive --throttle 2000 134 ``` 135 136 Output shows username, display name, user ID. User ID 1 is often the site administrator; display names may leak real names (OSINT value). 137 138 **OPSEC:** passive mode queries `/wp-json/wp/v2/users` (REST API, single request); mixed adds `/?author=ID` archive enumeration; aggressive adds login error messages. WordPress ≥ 4.7.1 may restrict the REST API via plugins. 139 140 ## Other Enumerations (timthumbs, config backups, DB exports, media) 141 142 ```bash 143 wpscan --url https://target.com -e tt # timthumb files (vulnerable image resizer) 144 wpscan --url https://target.com -e cb # config backups (wp-config.php.bak, ~, .old) 145 wpscan --url https://target.com -e dbe # database exports (.sql in web root) 146 wpscan --url https://target.com -e m1-15 # media files (requires Plain permalinks) 147 wpscan --url https://target.com -e tt,cb,dbe,m1-10 148 ``` 149 150 **Options:** `--timthumbs-detection`, `--config-backups-detection`, `--db-exports-detection`, `--medias-detection` (each passive/mixed/aggressive), plus matching `--*-list FILE` overrides. 151 152 ```bash 153 # Config backups (information disclosure) 154 wpscan --url https://example.com -e cb --config-backups-detection aggressive 155 156 # Database exports (critical if found) 157 wpscan --url https://example.com -e dbe --db-exports-detection aggressive 158 159 # Stealthy combined enumeration 160 wpscan --url https://example.com -e tt,cb,dbe --throttle 1500 161 ``` 162 163 - **Timthumbs:** old image resizer with known RCE (high severity if found; mostly pre-2014). 164 - **Config backups:** `wp-config.php.bak`, `~`, `.old` — contain DB creds and salt keys (critical if accessible). 165 - **Database exports:** `.sql`, `.sql.gz`, `.sql.bak` — full site compromise if accessible. 166 - **Media:** uploaded files via `/?attachment_id=N` (needs Plain permalinks). 167 168 ## Vulnerability Detection 169 170 Identify known vulnerabilities in core, plugins, and themes. Requires a WPScan API token. 171 172 ```bash 173 wpscan --url https://target.com --api-token TOKEN 174 wpscan --url https://target.com --api-token TOKEN -e vp,vt 175 wpscan --url https://target.com --api-token TOKEN -e ap,at 176 export WPSCAN_API_TOKEN=TOKEN && wpscan --url https://target.com 177 ``` 178 179 **Options:** `--api-token TOKEN` (25 req/day free, 250/day paid), `--wp-version-all` (check all known core versions). 180 181 ```bash 182 # Vulnerability scan with all plugins/themes and users 183 wpscan --url https://example.com --api-token TOKEN -e ap,at,u 184 185 # Check specific WordPress version vulnerabilities 186 wpscan --url https://example.com --api-token TOKEN --wp-version-all 187 ``` 188 189 Each vulnerability includes CVE/reference ID, description, affected/`Fixed in:` versions and a link. Vulnerability lookups are DB queries against WPScan's servers — **no extra HTTP requests to the target** (no OPSEC impact on the target). Token registration: register at wpscan.com, confirm email, retrieve the token from your profile. 190 191 ## Password Attacks 192 193 Brute-force WordPress user passwords (authorized testing only). 194 195 ```bash 196 wpscan --url https://target.com -U userlist.txt -P passwords.txt 197 wpscan --url https://target.com -U admin -P rockyou.txt --password-attack xmlrpc 198 wpscan --url https://target.com -P passwords.txt --password-attack wp-login 199 wpscan --url https://target.com -U admin,editor -P passwords.txt --password-attack xmlrpc-multicall 200 ``` 201 202 **Options:** 203 - `-U LIST`: Username(s) — single, comma-separated, or file path (auto-enumerates u1-10 if omitted) 204 - `-P FILE`: Password wordlist (required) 205 - `--password-attack MODE`: `wp-login` (default), `xmlrpc`, `xmlrpc-multicall` 206 - `--multicall-max-passwords N`: Max passwords per xmlrpc multicall (default 500) 207 - `--login-uri PATH`: Custom login URI (default `/wp-login.php`) 208 209 ```bash 210 # Brute-force single user with wordlist 211 wpscan --url https://example.com -U admin -P /usr/share/wordlists/rockyou.txt 212 213 # Force xmlrpc-multicall (fastest, WP <4.4 only) 214 wpscan --url https://example.com -U admin -P passwords.txt --password-attack xmlrpc-multicall --multicall-max-passwords 1000 215 216 # Force wp-login mode (always works, slower) 217 wpscan --url https://example.com -U admin -P passwords.txt --password-attack wp-login 218 219 # Stealthy password attack 220 wpscan --url https://example.com -U admin -P short-list.txt --throttle 5000 --random-user-agent 221 ``` 222 223 Attack modes by speed: **xmlrpc-multicall** (500 passwords per POST, WP <4.4 only, removed in 4.4+) → **xmlrpc** (1/POST to `/xmlrpc.php`, often disabled) → **wp-login** (1/POST to `/wp-login.php`, always available). Valid creds print as `[+] Valid Credentials Found`. 224 225 > **Warning — OPSEC.** Failed logins are recorded in the WP dashboard and server auth logs. WAF/security plugins (Wordfence, iThemes) block xmlrpc by default; lockout plugins block after N failures. High-volume attacks leave large log evidence. 226 227 ## Stealth Scanning 228 229 Minimize detection footprint during recon. 230 231 ```bash 232 wpscan --url https://target.com --stealthy 233 wpscan --url https://target.com --random-user-agent --detection-mode passive --plugins-version-detection passive 234 wpscan --url https://target.com --stealthy --throttle 2000 --max-threads 1 235 wpscan --url https://target.com --stealthy -e p,u1-10 --throttle 3000 --no-banner 236 ``` 237 238 `--stealthy` is an alias for `--random-user-agent --detection-mode passive --plugins-version-detection passive`. 239 240 **Options:** `--user-agent VALUE`, `--user-agents-list FILE`, `--detection-mode passive`, `--throttle MILLISECONDS` (auto-sets `--max-threads 1`), `--max-threads 1`, `--no-banner`. 241 242 ```bash 243 # Maximum stealth configuration 244 wpscan --url https://example.com --random-user-agent --detection-mode passive --plugins-detection passive --plugins-version-detection passive --themes-detection passive --throttle 5000 --max-threads 1 --no-banner 245 246 # Stealthy over Tor 247 wpscan --url https://example.com --stealthy --proxy socks5h://127.0.0.1:9050 --throttle 2000 248 ``` 249 250 Throttle guide: `--throttle 1000` ≈ 60 req/min, `--throttle 5000` ≈ 12 req/min. Stealthy mode drops a scan from 100-200 to ~20-50 requests but passive detection may fail to identify component versions. All requests are still logged even with stealth. 251 252 ## Authentication, Cookies & Headers 253 254 Scan authenticated areas or pass custom HTTP headers/cookies. 255 256 ```bash 257 wpscan --url https://target.com --http-auth username:password 258 wpscan --url https://target.com --cookie-string "wordpress_logged_in=value; wp_session=value" 259 wpscan --url https://target.com --cookie-jar /path/to/cookies.txt 260 wpscan --url https://target.com --headers "Authorization: Bearer TOKEN; X-Custom: value" 261 ``` 262 263 **Options:** `--http-auth username:password` (Basic/Digest), `--cookie-string "n=v; n2=v2"`, `--cookie-jar FILE` (Netscape/Mozilla format), `--headers "H1: v1; H2: v2"` (semicolon-separated). 264 265 ```bash 266 # HTTP Basic auth with special characters (single-quote to prevent shell expansion) 267 wpscan --url https://example.com --http-auth 'user:p@$$w0rd!' 268 269 # Scan with WordPress session cookies (logged-in user) 270 wpscan --url https://example.com --cookie-string "wordpress_logged_in_abc123=admin%7C123456%7Chash" 271 272 # Authenticated enumeration 273 wpscan --url https://example.com --cookie-string "wordpress_logged_in=value" -e ap,at,u1-100 274 ``` 275 276 > **Note —** HTTP Basic auth bypasses web-server restrictions, not WordPress auth. Use a low-privilege account for OPSEC. Cookie strings use `;` separators (not commas). `--http-auth` credentials are base64-encoded and visible in logs. 277 278 ## Proxy Configuration 279 280 ```bash 281 wpscan --url https://target.com --proxy http://proxy.example.com:8080 282 wpscan --url https://target.com --proxy socks5://127.0.0.1:9050 283 wpscan --url https://target.com --proxy socks5h://127.0.0.1:9050 284 wpscan --url https://target.com --proxy http://user:pass@proxy.example.com:8080 285 ``` 286 287 Supported protocols: `http://`, `socks4://`, `socks5://`, `socks5h://`. Use **`socks5h://`** for remote DNS resolution (prevents DNS leaks — recommended for Tor). Adjust `--request-timeout SECONDS` (default 60) and `--connect-timeout SECONDS` (default 30) for slow proxies. 288 289 ```bash 290 # HTTP proxy (Burp/ZAP interception) 291 wpscan --url https://example.com --proxy http://127.0.0.1:8080 292 293 # SOCKS5 with remote DNS (Tor), increased timeout 294 wpscan --url https://example.com --proxy socks5h://127.0.0.1:9050 --request-timeout 120 --connect-timeout 60 295 ``` 296 297 > **Note — Common errors.** `407 Proxy Authentication Required` → add `http://user:pass@proxy:port`. DNS leak with Tor → use `socks5h://` not `socks5://`. SSL errors through an intercepting proxy → `--disable-tls-checks` (trust implications). Ensure the proxy allows HTTPS to wpscan.com:443 for API lookups. 298 299 ## Custom WordPress Paths 300 301 Scan installs with non-standard directory structure. 302 303 ```bash 304 wpscan --url https://target.com --wp-content-dir custom-content 305 wpscan --url https://target.com --wp-plugins-dir custom-content/extensions 306 wpscan --url https://target.com --wp-content-dir wp-core/content --wp-plugins-dir wp-core/content/plugins 307 ``` 308 309 `--wp-content-dir DIR` and `--wp-plugins-dir DIR` are relative to the WordPress root. Discover the real paths from page source, e.g. `<link rel='stylesheet' href='/custom-wp/content/themes/twentytwentyone/style.css'>` → `--wp-content-dir custom-wp/content --wp-plugins-dir custom-wp/content/plugins`. Set in wp-config.php via the `WP_CONTENT_DIR` / `WP_PLUGIN_DIR` constants. 310 311 ## Output Formats 312 313 ```bash 314 wpscan --url https://target.com -o report.txt 315 wpscan --url https://target.com -f json -o report.json 316 wpscan --url https://target.com -f cli-no-colour -o report.txt 317 wpscan --url https://target.com --format json --output results.json 318 ``` 319 320 **Formats:** `cli` (colored, default), `cli-no-colour`/`cli-no-color` (plain text), `json` (machine-readable). 321 322 ```bash 323 # JSON output + parse with jq (WordPress version) 324 wpscan --url https://example.com -f json -o report.json && jq '.version.number' report.json 325 326 # JSON output + parse vulnerabilities 327 wpscan --url https://example.com --api-token TOKEN -f json -o report.json && jq '.plugins[].vulnerabilities' report.json 328 ``` 329 330 JSON top-level keys (v3.8.x): `target_url`, `version`, `interesting_findings`, `plugins`, `themes`, `users`, `vulnerabilities`. Each plugin/theme entry carries `slug`, `location`, `version`, `vulnerabilities[]`. 331 332 ## Installation 333 334 ```bash 335 # Kali / Debian / Ubuntu (apt) 336 sudo apt update && sudo apt install wpscan 337 wpscan --version 338 339 # Ruby gem (Debian/Ubuntu) — needs Ruby 3.x+ 340 sudo apt install ruby-full ruby-dev libcurl4-openssl-dev build-essential 341 sudo gem install wpscan 342 343 # Fix nokogiri dependency error (common on Debian/Ubuntu) 344 sudo apt install ruby-dev build-essential libxml2-dev libxslt1-dev zlib1g-dev 345 sudo gem install nokogiri --platform=ruby 346 sudo gem install wpscan 347 348 # Docker (no local Ruby needed) 349 docker pull wpscanteam/wpscan 350 docker run -it --rm wpscanteam/wpscan --url https://example.com --api-token TOKEN 351 352 # Docker with output file (mount volume) 353 docker run -it --rm -v /tmp:/output wpscanteam/wpscan --url https://example.com -o /output/report.txt 354 355 # Git clone (development version) 356 git clone https://github.com/wpscanteam/wpscan.git && cd wpscan 357 bundle install 358 ./bin/wpscan --url https://example.com 359 ``` 360 361 ## Sources 362 363 - https://github.com/wpscanteam/wpscan 364 - https://wpscan.com/docs/ 365 - https://wpscan.com/api 366 - https://www.kali.org/tools/wpscan/