bugbounty

Exploit-DB Local File Inclusion (Possible RCE/RFI)

8:05 PM



I am writing this blog post because both the teams that handled this bug were quite amazing. (Vulnerable 3rd party and Offensive Security) They acknowledged, fixed and rewarded my report in <1hr of my submission. (both of them) This, for someone with experience with responsible disclosure is unbelievable.

So it starts out like this, Offensive-Security's Exploit-db announced they just launched their new appearance. I checked it out, it’s quite beautiful, less darker and all… a white-hat’s place. It looked less like Inj3ctor and more like exploit-db. 

I noticed they are running wordpress, with a number of plugins. But they obviously were all updated and running latest version. I had to find a 0day. So I downloaded their new caching plugin for page performance, WP-ROCKET. (which by the way handled the bug quite well, and even acknowledged my report in multiple ways, Thank you!)

The code looked good, I found no SQLi, no XSS. But then, a very silly page seems to appear with a silly code.
/wp-content/wprocketfolder/inc/front/process.php line 44,

Says include ($rocket_config_path . $host . '.php');

Where $host is pre-defined as:

44: $host = trim(strtolower($_SERVER['HTTP_HOST']), '.');

This page can be accessed to anyone and requires no wordpress authentication. The HTTP_HOST header can be manipulated simply by tampering with the HOST header. (Edit: This is only applicable if certain Apache/php.ini are fulfilled.) I then wrote about the bug to Offensive-Security, they responded 12mins later saying they disabled the plug in.

In an LFI theory, an attacker can poison log files and include them as ../../logfile to cause Remote code execution. (RCE) Practically that would be hard to exploit for RCE because an attacker would need to bypass the WAF they are running called Sucuri. And also php doesn’t let null termination (%x00) work (because its patched since < 5.2.1), this would be difficult to achieve But...

This can be exploited by using php://filter for local file inclusion by sending a HOST headers like
php://filter/convert.base64-encode/resource=index then when the include happens, $host.'php'); our resource parameter will get index.php, this forces PHP to base64 encode the file before it is used in the include statement. From this point its a matter of then decoding the base64 string to obtain the source code for the PHP files. Simple yet effective..

Or This theoretically would also had been exploitable to RFI (Remote File Inclusion) if the path wasn't relative. In absolute URL cases, we can use the data:// Scheme to cause RFI. By encoding a PHP script in base64 and then URL encoding any special characters contained within this string we can successfully execute a script. Below example shows how phpinfo() can be executed using the above script to enumerate more information about the targe. Or a simple RCE by using the expect:// scheme (same as the one that caused the XXE RCE in Facebook)

<? phpinfo(); die();?>

// Base64 Encoded
PD8gcGhwaW5mbygpOyBkaWUoKTs/Pg==

// URL + Base64 Encoded
PD8gcGhwaW5mbygpOyBkaWUoKTs%2fPg==

// Final URL in HOST
data://text/plain;base64,PD8gcGhwaW5mbygpOyBkaWUoKTs%2fPg==

The die() statement is there to prevent the execution of the rest of the script or the execution of of the incorrectly decoded ".php" string which is appended to the stream.

Using a data stream over a standard remote or local file inclusion has several benefits:

  • It doesn't require a remote server.
  • Its doesn't require a null-byte to be appended to the end of the script.
  • It works behind a firewall that blocks outbound traffic.

However, exploitation was blocked because of a fair WAF called Suruci and The include being relative. Nevertheless, they treated the bug as critical as it is, and pushed a fix in < hr of my initial report  and added my name to their Special Thanks page.(of course with a bounty)!

Special Thanks to Julio Potier, a programer of the WP-Rocket team. He acknowledged my report, fixed the bug, and even issued a generous bounty.

Timeline

April 19, 6:54 am – Initial Report
April 19, 7:08 am – Confirmation
April 19, 7:43 – Complete Fix + Bounty