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

bugbounty

Facebook: Another Linkshim Bypass

12:48 PM


I wasn't going to post about it then I thought it 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 initial 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. 

First I am going to talk about the relevant and great 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: 
//prompt.ml%2f@á„’.ws/

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 external 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 FB did blacklisted //. The next try should be \/evilzone.org, since most browsers render \ back to / this usually bypass the check and create //evilzone.org

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

I then was talking to @FransRosen and he mentioned about a technique that could still cause another bypass. \%09/@site.com

This basically should be equivalent to //@site.com and since their regex didn't contain \%09/ , \%0D/ or \%0A/ in its banlist, this results in // being back because the %09 will obviously get ignored while parsing.  We can keep adding as many of these in between. And the complete linkshim bypass will look something like:




Feb 1, 2015 6:33am - Initial 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! :-)


bugbounty

Facebook’s Oculus – Cross-Site Content Hijacking (XSCH) to Bypass SOP

8:42 AM




First off, before going in-depth about this I would like to paste you what a crossdomain.xml file is,here is something that are taken from Ookla, you can read more here.

What is the crossdomain.xml file?

The crossdomain.xml file is a cross-domain policy file. It grants the Flash Player permission to talk to servers other than the one it's hosted on.

In what circumstances do I need to use one?

You need a crossdomain.xml file when your Speedtest uses external hosts as testing servers.

Crossdomain.xml files

Flash Player’s default security model enforces the same origin policy similar to contemporary browsers and does not allow cross domain data read operations. However, it can make exception to this rule and disregard its default security model if a website in question hosts a cross-domain policy file (named crossdomain.xml) to allow data access from other domains. Insecurely written cross-domain policy files can expose critical application data over the internet. The example policy file below shows once such example where the website opens itself to read access from every running instance of Flash Player.

This forexample is how a (super) vulnerable crossdomain file looks like,


<cross-domain-policy>  
      <allow-access-from domain="*" />
</cross-domain-policy>


When flash requests to access that domain, it first asks the domain if it’s okay to snoop its contents. It does that by requesting domain.com/crossdomain.xml file and reading it, that crossdomain file says "Allow-access-from *(all) domains". This means, where ever our flash file is hosted (attacker.com/hack.swf), it will be able to read the contents of domain.com. This is much like a Cross Site scripting, but less in some case. We can only request and read, we cannot write. So it less.

Using this we can steal AntiCSRF tokens, craft CSRF exploits. Read html files using victim sessions (Messages, account balance…)

Here is a great example,”

  1. A user logs on to the banking website.
  2. The user then visits another website in different browser tab and that website hosts a malicious Flash file to retrieve user information from the bank website.
  3. When the Flash Player notices an attempt to perform cross-domain read operation, it retrieves crossdomain.xml file from the bank website to discover the permitted operations.
  4. It then sends out a read request to a known bank URL that returns sensitive information like user bank account numbers, account balance etc…
  5. The browser adds user’s session cookies to the outgoing requests and since the user is logged in, the malicious Flash file is served with critical user information.
  6. Th Flash file then passes it on to the malicious server.


There is a particular flash exploit for this attack by Gursev Singh Kalra here.http://pastebin.com/EwqkGkxp

I was bored so I gave a shot of each oculus domain. All turned out to be safe, excpet one. It says

<allow-access-from domain="*.oculus.com" secure=”true”/>

It means everything that is hosted at *.oculus.com have read access at developer.oculus.com domain.  


Luckily, I recently saw support.oculus.com have an upload box if you cut a ticket via ZenDesk. While submitting a ticket, you can also upload image files. You see what I am going with this? I made my malicious flash.swf file, change the extension to flash.jpg, upload it at support.oculus.com and that file now have access to developer.oculus.com because the crossdomain allowed it.

The great about flash is, despite the file Mime, or format say flash.jpg, when we embed it as flash, it will act like flash despire its content/mime type.  

The exploit Scenario follows as:

1.       1. Create a malicious flash.swf that does malicious action, like read antiCSRF tokens or   messages.

2.       2. Change the extension of flash.swf to flash.jpg

3.       3. Navigate to support.oculus.com, create a ticket and upload our malicious flash.jpg file as a supporting image to the support team

4.       4. In our malicious domain (say attacker.com) host,  


<object type="application/x-shockwave-flash" data="https://support.oculus.com/attachments/token/APToMFwKw6O45WRIS5lf1HTP7/flash.jpg" width="1" height="1">

<param name="movie" value="https://support.oculus.com/attachments/token/APToMFwKw6O45WRIS5lf1HTP7/flash.jpg" />

</object>



5.       6. Now we navigate our victim to attacker.com and as soon as the flash files runs, Boom! We get everything we need. 

   Facebook had an amazing (better?) support about this. I got the fix (less than 9hrs)
   Hope you enjoyed the post! Comments would be nice! :)
    

   Report Timeline:

      Dec 29, 2014 6:59am - Initial Report
      Jan 27, 2015 9:09am  - Facebook Initial Confirmation
      Jan 27, 2015 6:55pm  - Fix!
     
Great cooperation guys! and I would like to thank the Facebook Security team and the program it self.

Conclusion:


-          Permit access from your crossdomain.xml because a simple mistake or “*” can cause a disaster.

-          In another option, make your uploaded files have a content-disposition header with appropriate values. 
 

bugbounty

XSS Bug on Facebook Studio

8:41 AM



VL-MAG: http://magazine.vulnerability-db.com/?q=articles/2014/12/11/whitehat-hacker-discovered-details-application-side-facebook-studio-dashboard

This is a cool Second-Order-Injection XSS against Facebook Studio that was caused by data input on Facebook Mobile (Facebook Studio).

This vulnerability is created because of improper user input parsing. First, I noticed facebook-studio.com doesn’t use Linkshim (malicious link detection system for Facebook). When I saw that, I immediately wrote to Facebook about it. But then I realized, this is not exploitable because it fetches the URL’s from My Facebook profile. Take: Evilzone.org is a site blocked by Linkshim.

Meaning, if I add “google.com” as my website on Facebook, it will be fetched to my Studios account. which means, there needs to be no linkshim because it was first checked on Facebook.

Linkshim uses a list of sites to identify if the site is malicious or not. So bypassing basically includes cheating the linkshim into thinking our site is not included. As always, I started with case-sensetivity bypasses, hoping, if evilzone.org is blocked, to bypass it with EVILZoNE.org, it obviously didn't work.

Then I tried URL encoding. There is a value in html called shy. That basically, shies/hides elements. This tag can be used in href elements. So <a href=”evil&shy;zone.org” >X</a> is equvallent to evilzone.org so all I had to do is add evil&shy;zone.org as my website using the mobile interface of Facebook (since the main site sends requests to verify, and the mobile version doesn’t)

So when Facebook studio fetches my URL from my Facebook profile and add it in href tag (hoping it is a safe link checked by Linkshim, and it is), it will become “<a href=”evil&shy;zone.org” >X</a>” when clicked redirects to evilzone.org, which is considered a linkshim evasion.

Seeing the source, I then wondered why &shy; still itself and not encoded. So I tried my chance with http://something.com”><script>alert(0);</script> but that link become

<a href=” http://something.com”” target=’_’ >X</a>
It basically means, the inputs < , >, /  and anything following them is filtered. So I tried event handler XSS’es since quotes aren’t blocked with payloads like 


So that will be rendered as
<a href=” http://something.com”onmouseover=”alert(1); //&shy;.” target=’_’ >X</a>
The bad news is I can’t make it self-executable even using autofocus and onfocus because it is href attribute. So I tried ways of making this self-executable. Then, I  use CSS to make the font very big, so it will fill the screen. So onmouseover will automatically get it triggered because the mouse will be all over it. Note: since it’s a URL for Facebook, no spaces were allowed. 

That was the final payload I added to my Facebook account, as my website. The problem with Facebook was that when adding it to the database, I don’t know why Facebook didn’t html entity it. So when Studio featched the contents, it became


And creating us a nice self executing XSS.


Nov 22, 2014 7:12am - Notified Facebook
Nov 24, 2014 1:30pm - Facebook Notified its out of scope
Dec 2, 2014 10:42am - Issue got fixed.
Dec 9, 2014 08:03am - Public Disclosure

Conclusion

No matter where the source is, do not trust user input data even while fetching it from a trusted source.