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

// URL + Base64 Encoded

// Final URL in HOST

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.


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


Facebook’s Parse – DOM XSS

2:01 PM

These are just some simple bugs that were present in Parse site. Considering the ease of exploitation, I am posting this to make sure other people can scan the JS code more intensively and find more bugs, it’s very likely.
The first vulnerable code was present in https://parse.com/apps/user_management:

document.getElementById('content').innerHTML =
          '<h1>This page lets you host Parse.com content from your own domain.</h1>' +
          '<p>Right click <a href="' + window.location.pathname + '">here</a> to save this page. ' +
          'Upload it to your own website and paste the URL in the "Parse Frame URL";

The problem is present because of using document.getElementById('content').innerHTML
With  window.location.pathname without no proper encoding.
This can be exploited with https://parse.com/apps/user_management/?/<payload> and that will be written in the href tag as a pathname. Ouch!

The second one at this same page:
if (param == 'link') {
            link = urlParams['link'];
var iframe = document.createElement('iframe');
iframe.setAttribute('src', link);

This one is easy to exploit, ?link=/closesrc><payload> would do the job!
some effective fixes have been in place now to use encodeURICompnent()! :)

Hope you find this useful and find similar bugs!

Mar 30, 2015 – Initial Report
Mar 30, 2015 – More clarification sent
Mar 31, 2015 – Report got escalated
Apr 2, 2015 – Fix and Bounty!


Exploiting PHP Upload forms with CVE-2015-2348

4:06 AM

Today I would like to post about a recent bug I have found in PHP, CVE-2015-2348.
This bug is fairly severe. (considering the amount of developers affected).
I have to admit checking the file extension and saying a file is safe can still cause many
other security issues. However, checking for this exact vulnerability in your code is pretty
unrealistic, considering it can pass the Content-Type, Extension, Mime type, size checks...
etc won't save you from this.

The issue occurs in the very popular move_uploaded_files php function that is used to handle
uploaded files most of the time. This function checks to ensure that the file designated by
filename is a valid upload file (meaning that it was uploaded via PHP's HTTP POST upload
mechanism). If the file is valid, it will be moved to the filename given by destination.


move_uploaded_file ( string $filename , string $destination )

The problem with it is that there is a way to insert null-bytes (fixed multiple times before,
i.e: CVE-2006-7243). Using null-bytes an attacker can convince an upload box to ignore
extension checks and that the file is fairly safe and valid and upload malicious files that
can cause RCE. using the character \x00

I am going to take DVWA for an example here. DVWA's highest level is meant to be unbroken
for number of issues. the high upload box is meant to teach developers the safe way of handling
a safe upload. Lets just exploit that.

Here is the code snippet from https://github.com/RandomStorm/DVWA/blob/master/

$uploaded_name = $_FILES['uploaded']['name'];
$uploaded_ext = substr($uploaded_name, strrpos($uploaded_name, '.') + 1);
$uploaded_size = $_FILES['uploaded']['size'];

if (($uploaded_ext == "jpg" || $uploaded_ext == "JPG" || $uploaded_ext == "jpeg" ||
$uploaded_ext == "JPEG") && ($uploaded_size < 100000)){

if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {

$html .= '';
$html .= 'Your image was not uploaded.';
$html .= ''; }
else {
$html .= $target_path . ' succesfully uploaded!';

This is yes vulnerable to number of exploits (like XSCH, XSS and more), but not RCE.
Because since PHP 5.3.1 Null bytes are deprecated.

The problem with DVWA is that its passing user provided name to the move_uploaded_file()

Expected behavior for PHP to create:


That file should have created the file "file.php\x00.jpg"

Reality creates: file.php

This clearly bypasses the extension check. It has been proven many times the GD libraries
can also be defeated ( getimagesize(), imagecreatefromjpeg()... ),
read this by @secgeek for example.

Now even if you have had done multiple checks for this, it will be highly unlikely you blacklisted
the char \x00 so most upload forms running PHP before 5.4.39, 5.5.x before 5.5.23, and 5.6.x
before 5.6.7 are vulnerable for this particular attack.


If you are on a vulnerable server, update homie!


Facebook Bug Bounty: Clickjacking

10:14 AM

Note: this is actually a guest post from a friend, Sahad Nk with his recently patched Facebook Clickjacking bug. The exploit was really interesting so I really hope you enjoy it.


According to OWASP: Clickjacking, also known as a "UI redress attack", is when an attacker uses multiple transparent or opaque layers to trick a user into clicking on a button or link on another page when they were intending to click on the the top level page. Thus, the attacker is "hijacking" clicks meant for their page and routing them to another page, most likely owned by another application, domain, or both.

Using a similar technique, keystrokes can also be hijacked. With a carefully crafted combination of stylesheets, iframes, and text boxes, a user can be led to believe they are typing in the password to their email or bank account, but are instead typing into an invisible frame controlled by the attacker.

According to me: Clickjacking is an interesting and simple way of exploiting a web application that can lead to serious issues (transfer funds, messaging...). The idea is actually really simple:

We frame a certain website A within an Iframe and using stylesheets, we made it invisible/hidden (when it exists in the background) and reconstruct another site before it. So while you click something on the attacker controlled site, I can actually make you click a button in the framed website.

Owasp have a good example for ClickJacking: For example, imagine an attacker who builds a web site that has a button on it that says "click here for a free iPod". However, on top of that web page, the attacker has loaded an iframe with your mail account, and lined up exactly the "delete all messages" button directly on top of the "free iPod" button. The victim tries to click on the "free iPod" button but instead actually clicked on the invisible "delete all messages" button. In essence, the attacker has "hijacked" the user's click, hence the name "Clickjacking".

The simplest and effective fix for this is the X-Frame-Options header. Even though, Facebook was using one, here is how I bypassed it to make me an attacker do post a status update. :)

The Exploit:

The exploit is really simple and effective; Facebook defends click-jacking in 2 ways. One is alternative to the other. They also use a technique called Frame-busting (using javascript to deny framing request). On interfaces which don't have a JS support it is sending XFO, not as a
HTTP header, but in a meta tag by putting it in a <noscript> tag

<noscript><meta http-equiv="X-Frame-­Options" content="deny"> </noscript>

Meta-tags that attempt to apply the X-Frame-Options directive DO NOT WORK. For example, <meta http-equiv="X-Frame-­Options" content="deny">) will not work. You must apply the X-FRAME-OPTIONS directive as HTTP Response Header.

The main point here is browsers ignores what is given in meta tag and do not defend framing, (tested in Firefox 35).

On interfaces which require JS support, it is possible to bypass JS frame-busting by giving a sandbox in the iframe like:

<iframe id="clickjacking" src="https://­iphone.facebook.com/­dialog/feed?app_id[APP ID]&picture­=http://example.com/­example.JPG&name=Test­&description=This%20­is%20a%20test&redire­ct_uri=http://­example.com/" width="500" height="500" scrolling="no" frameborder="none" sandbox="allow-forms­"> </iframe>

Simple as that, it was possible to iframe Facebook and make you do undesirable amount of things.
Here is a video demonstrating the seriousness of how this exploit might have been abused:

Reported - March 20
Clarification - March 21
Fix & Bounty  - March 24

Hope you enjoyed it! and thanks Sahad Nk!


Facebook: Another Linkshim Bypass

12:48 PM

I wasn't going to post about this but it turns out, this could be an interesting article to post because this is the 3rd vulnerability that got fixed in the same parameter 6 months later.

You can find my inital linkshim bypass to this exact position which later turns out to be XSS if you click here. In the first bug I found in the continue parameter, it is possible to bypass linkshim and force a redirection to a site before being checked but then, XSS. later, this resulted some media attention and now when I find another linkshim bypass, I taught why no one else actually found this bypass, after the first got public. and that is one of the main reasons I am posting this.

I am going to talk about completely irrelevant but cool in a way technique I learned from the prompt.ml XSS Challenge(s) 4, you can find the DOM XSS challenge here. consider the code:

function escape(input) {
    // make sure the script belongs to own site
    // sample script: http://prompt.ml/js/test.js
    if (/^(?:https?:)?\/\/prompt\.ml\//i.test(decodeURIComponent(input))) {
        var script = document.createElement('script');
        script.src = input;
        return script.outerHTML;
    } else {
        return 'Invalid resource.';

This is the JS source code of challenge 4. they basically want you to bypass a regex to get an external redirection. And the main problem here is that it uses decodeURIComponent(), a function that decodes supplied input from URL encoding. In this case, we can trick the browser believe the prompt.ml domain (allowed by the regex) belongs to our URL. This should be very simple using HTTP auth, like http://prompt.ml@attacker.com the above URL redirects to attacker.com and should bypass the regex because having the prompt.ml.

To bypass decodeURIComponent(), we simply have to use %2f which is a URL encoded representation for the /. And our bypass is:

The trick to solve the level with 17 characters only lies hidden in a transformation behavior some browsers apply when converting Unicode characters to URLs. A certain range of characters resolves to three other characters of which one is a dot - the dot we need for the URL. The following vectors uses the domain 14.rs that can be expressed by two characters only.”

A url that starts with two forward slashes is treated as absolute by browsers.
Something similar seems to cause this issue (server-side), when given the continue parameter,

This successfully will send example.com for a check to a linkshim before extermal redirection which means https://m.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&confirm=h&continue=http://evilzone.org should be malicious.

Now a stupid enough URL validator will consider //evilzone.org a relative location and won’t allow us create a hyperlink like <a href=”//evilzone.org”> and Facebook obviously have black listed //

The next try should be \/evilzone.org, since most browsers render \ back to / this usually bypass the check and create //evilzone.org (you can read more about this from @homrkov’s Evolution of Open Redirection post)

So // and \/ got caught. At this point I concluded the linkshim uses number of blacklist based checks from \\, //, \/ and started fuzzing.

Thanks to @FransRosen, he told me about a technique that could create this bypass. \%09/@site.com
This basically should be equivalent to //@site.com and since the checker won’t find \%09/ , \%0D/ or \%0A/ blacklisted, this will result // because the %09 should obviously get ignored while parsing. And my complete linkshim bypasser will look something like:

Note: Upon testing, I saw the tel: and mailto: protocol’s are allowed in the continue parameter, I reported this but they said they will not act on it quick and should remain there for sometime.
To abuse the tel: protocol, we need the victim to click on the continue button, https://m.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&confirm=h&continue=tel:+251928475100 in some phones, this automatically start calling to that number (iPhones, some version). 
To abuse the mailto: protocol, we can force victim’s to attach a file from their local HDD and send it to our address, you can read about the mailto: protocol at http://support.microsoft.com/kb/279460
Anyway, the format is:

Using that, we construct our payload:

should force some clients (not thunderbird or outlook), send a mail with attachment from their local HDD. This is a known issue and I think is going to stay that way now I have asked them.

Feb 1, 2015 6:33am - Inital Report
Feb 1, 2015 6:47am - More Clarification sent
Feb 2, 2015 6:11am - More Classfication asked 
Feb 3, 2015 1:04pm - Some more clarifications sent
Feb 4, 2015 11:25am - Escalation of bug    
Feb 23, 2015 11:00am - Bug Fixed
Thanks you for reading! :-)