Friday, 20 February 2015

From Case-Insensitive to RCE

This post was written by The DarkRaver. He's a close friend and one of the best skilled security professionals that I have ever met. He's also known by publishing tools such as dirb or sqlibf that I strongly recommend.

Go ahead with his post:


Some time ago, I was doing a webapp penetration testing when I found something really interesting. The application was coded in PHP and it relied on some commercial components. Soon I found lots of XSS and SQLi vulnerable forms, but we won't focus on that in this post.

Suddenly, I realised that requesting the same page in uppercase or lowercase changed its behavior. The webserver was based on Apache and Linux (case sensitive) but the files seem to be hosted in a cases insensitive filesystem (maybe a NAS share?), so when I requested page.php it responded as expected, but when I requested page.PHP its source code was shown.

That vulnerability allowed to review the commercial application's source code, where I found several potentially dangerous functions such as "include()" and "include_once()" that could be vulnerable. No other dangerous functions such as "system()", "open()" or "file_get_contents()" were found.

A few minutes later I could confirm that at least one of those "include_once()" functions was vulnerable to LFI and exploitable. However, only files with .js extension could be loaded.

I tried several ways to bypass this protection, such as null byte, long paths, etc, but nothing seemed to work. So... we're tied to that. How we could upload or create a .js file in the local filesystem?

The upload forms didn't allow that kind of extensions and we weren't able to create files inside the server. Or... maybe we were? What about the following piece of code?

It was a feature that allowed to cache JavaScript files on disk! But... How could we inject custom content in those cached files?

An in-depth look showed that some JavaScripts were generated from a template and one of them included some user controled parameters. That sounds great!

Even better, the injectable parameter was the same that was vulnerable to LFI, so we could find a way to exploit both vulnerabilities at the same time.

JavaScript files were stored in a path like that: "/cache/".$offv.$theme.$lang.$type.$name.".js" , where $offv was the user provided input and the other parts could be easy guessed looking at the source code. So... the exploit string should be as follows:

However, I got a "500 - Internal Server Error". What the hell??? Something was terribly crashing. How we could fix it? I tried some other PHP functions such as "system()", "file_get_contents()" and "phpversion()" but most of them crashed in the same way.

Wait, what if the exploit works but it crashes at some point after that? what if we try to "exit()" the execution?

It works! Finally I had Remote Code Execution in the server, and everything began with a small source code leak caused by a case-insensitive filesystem. Small things sometimes cause big troubles.

Thursday, 5 February 2015

An IE Same Origin Policy Bypass story

A couple of days ago I was reading my feeds when suddenly a headline caught my attention: "Serious bug in fully patched Internet Explorer put user credentials at risk". A same-origin-policy bypass in Internet Explorer had been released. This is a really critical vulnerability, because SOP provides isolation between different websites inside our browser, and avoid evil sites to get access to other sites and modify its content and so on.

I have been taking a look for the last few hours and it definitely works. The provided PoC works but perhaps isn't the most practical approach. As far as I know, details of this vulnerability haven't been published apart from the PoC itself, so let's have a look to the PoC. I have prepared my own PoC, just to see if I could use this vulnerability for more evil purposes.

At first sight, the vulnerability seems to be a race condition or similar. There are two iframes, the first one loads a dynamic webpage, for example 1.php. Its source code wasn't published with the PoC but it simply waits for a few seconds and then it redirects to the same url than the second iframe.

Both iframes load a webpage in the target website. It's important to find a webpage that could be loaded inside an iframe because if not the vulnerability isn't exploitable. Providers such as Google, Facebook, etc usually configure their sites with the "X-Frame-Options" header in order to avoid ClickJacking attacks.

However, a single page with no "X-Frame-Options" in the domain is enough for us, and this is not as difficult to find as it seems. There are two well known resources that aren't protected in most websites: robots.txt (the one used by the original author) and favicon.ico (I used that one because it looks better for a practical attack).

There is a function called "go()" that makes the real exploitation. It's difficult to read so let me decode it for you.

Here is where interesting things happen. There are some "alert" and "eval" calls that seem to be important. I couldn't figure out why, but if you change them it won't work. This is the tricky part in this vulnerability.

It gets the second iframe that we were talking before and store it in a variable "x". Then it waits a few seconds (1 second in the code) and shows an alert message. As I previously said, that alert seem to be important so we can remove it, but we can use a message that won't warn the user that something bad is just about to happen. After that, when the first iframe has already changed from my evil domain to the target domain (because of 1.php) a piece of javascript and HTML code is injected in that second iframe. We shouldn't be able to to that, because it's a different domain, but we are. The same origin policy has been bypassed.

Let's see what a victim would see:

Some countries have specific laws about cookies and a warning message is needed at most websites, so users are used to click "OK".

When I injected the javascript and HTML code in the iframe, I used a Google button. It isn't the most beautiful blog but well... It looks like a real blog :)

The Google authentication page is opened. Everything looks fine but I have changed the form action using the injected javascript code.

Done! A really cool vulnerability. I can't wait for more details about the vulnerability. Let's see if in a few days we can know why "alert", "eval" and "setTimeout" are sometimes as important as they are.