Web security subtleties and exploitation of combined vulnerabilities

Published: 2015-06-25
Last Updated: 2015-06-25 08:56:25 UTC
by Bojan Zdrnja (Version: 1)
4 comment(s)

The goal of a penetration test is to report all identified vulnerabilities to the customer. Of course, every penetration tester puts most of his effort into finding critical security vulnerabilities: SQL injection, XSS and similar, which have the most impact for the tested web application (and, indeed, it does not hurt a penetration tester’s ego when such a vulnerability is identified :)

However, I strongly push towards reporting of every single vulnerability, no matter how harmless it might appear (and my penetration team coworkers sometimes complain about this, but let’s prove them wrong).

Here we’ll take a look at how two seemingly low risk vulnerabilities can be combined into a more dangerous one.

Accepting parameters in GET and POST requests

When processing parameters/responses received from the client, most of the today’s web applications rely on POST HTTP requests. This is a preferred way of sending client-related input/output from the browser since it will not be visible in web server’s (or proxy’s) logs. One of the tests I normally do is to check if the application accepts same parameters in GET HTTP requests. Let’s take a look at this.

The “official” request looks like this:

POST /page HTTP/1.1
Host: my.example.local
… (other headers)

parameter=value&secret=secret_value

Now we can try to issue the same request as a GET HTTP request:

GET /page?parameter=value&secret=secret_value HTTP/1.1
Host: my.example.local
… (other headers)

If this worked it means that the tested web application (the tested page/script) accepts parameters from any request. While this by itself is not really a security vulnerability, it is not a perfect way for receiving and processing parameters as we will see below. Additionally, keep in mind that this makes an attacker’s job a bit easier – instead of working with POST HTTP requests he can simply put everything into GET HTTP request (yeah, it works for the defenders as well since we’ll see what he put into the request).

A seemingly harmless XSS vulnerability

While further testing this application we found an XSS vulnerability. For sake of simplicity let’s say it’s an anonymous application that has no login forms. However, since the application depends on a certain workflow, and since the XSS vulnerability was found in the 3rd step of the workflow, it does require a valid session cookie (a JSESSIONID cookie).

What does this mean? It means that the attacker cannot exploit the XSS vulnerability: if the request to the vulnerable page is made without a valid JSESSIONID cookie, the application simply redirects the user to the front page (the first step of the workflow). Even if the victim now again clicked on the malicious link, it still wouldn’t work because the tested application checks the workflow phase/step and if it is not correct again simply redirects the user to the front page.

Ahh, such a disappointment after finding a very nice XSS vulnerability: the attacker can really exploit only himself and that’s no fun at all. Or is there another way?

Taking this a bit further

Remember how we figured out that the application accepts parameters in both GET and POST HTTP requests above?
Let’s see what else can be submitted through such requests. The cookie, which is crucial to the behavior of the tested application is a simple JSESSIONID cookie that looks like this:

Cookie: JSESSIONID=560308266F93351159D8D20732C637FA

Since the cookie is normally sent as part of a header, the attacker cannot get the victim’s browser to set the cookie for the target web application, at least not without exploiting another vulnerability – such as an XSS vulnerability – but remember that we cannot exploit it without a valid cookie. Catch 22 isn’t it?

But, let’s not lose hope. What if we try to submit the cookie as a parameter in a GET or POST HTTP request? Such a request would look like this:

GET /page?JSESSIONID=560308266F93351159D8D20732C637FA¶meter=value&secret=secret_value HTTP/1.1
Host: my.example.local
… (other headers)

Bingo! This worked – the tested web application happily took and parsed all submitted parameters, even the JSESSIONID parameter that should be normally delivered as a cookie. The developers probably wanted to be as flexible as possible.

Combining the vulnerabilities into an exploit

So, the attacker can now deploy the following attack:

  • Create a new session where he navigates to the required screen. The application now “knows” that the JSESSIONID cookie that was given to the attacker relates to a session that is at the vulnerable screen.
  • Create a malicious URL that exploits the XSS vulnerability. Append the JSESSIONID parameter that contains the attacker’s cookie value to the malicious URL. This URL will work because the vulnerable web application will verify the session state and see that the user is accessing a valid screen in the workflow.
  • Send the malicious URL to the victim, wait and profit.

Finally, last thing to discuss is maybe what we exploit with the XSS vulnerability in the first place: typically the attacker tries to steal cookies in order to gain access to the victim’s session. Since here sessions are irrelevant, the attacker will not use XSS to steal cookies but instead to change what the web page displays to the victim. This can be used for all sorts of phishing exploits and, depending on the URL and context of the attack, can be even more devastating than stealing the sessions.

--
Bojan
@bojanz
INFIGO IS

Keywords: web xss
4 comment(s)

Comments

You are confusing things. That the application treats get and post parameters the same have nothing to do with the exploit. On the contrary it is just as easy for an attacker to have a client send post parameters as get parameters. Just have a hidden form on a page and submit it via javascript or a styled submit button.
What the described exploit hinges on is that get parameters are treated the same way as cookies. And that is a totally different matter.
Hi Bojan,

Please provide small code snippet with your write-up, so that it will make more sense to the readers. Because this will help other members to address the similar situation or else it may lead to report "false positive" issue.
[quote=comment#34425]You are confusing things. That the application treats get and post parameters the same have nothing to do with the exploit. On the contrary it is just as easy for an attacker to have a client send post parameters as get parameters. Just have a hidden form on a page and submit it via javascript or a styled submit button.
What the described exploit hinges on is that get parameters are treated the same way as cookies. And that is a totally different matter.[/quote]

You are right that the main issue here is that the application accepts cookies as parameters.
However, besides that, I think that the application should always accept parameters only as the expected request: if the user should make a POST request (because that's how the application's workflow has been built), it should not accept same parameters as a GET request.

Another reason for this is that it makes it easier for attacker to send phishing attacks against clients.
If the application accepts only POST requests (where required), the attacker must use a 3rd site to create such a POST request.
With GET requests, the attacker can send the malicious URL directly in an e-mail and the victim just has to click on it (and the victim can indeed verify that the request leads to the expected web site).

So, as I wrote, this is subtle, and a minor detail, but still something (IMHO) worth consideration.

Bojan
[quote=comment#34427]Hi Bojan,

Please provide small code snippet with your write-up, so that it will make more sense to the readers. Because this will help other members to address the similar situation or else it may lead to report "false positive" issue.[/quote]

Hi - I'll see what I can include to make it easier to understand :)

Bojan

Diary Archives