Tuesday, March 2, 2010

Bypassing CSRF protections with ClickJacking and HTTP Parameter Pollution

This idea occurred to me a few weeks back when discussing the potential impact of ClickJacking attacks with Luca. Submitting forms using ClickJacking is hard work and is only successful in very rare scenarios. The Twitter ClickJacking attack was one famous instance where form submission was involved, but it was a form that was submitted over ‘GET’ request.

In this post I will discuss a technique that can be used to bypassing any CSRF counter measures and submit POST method -based forms with attacker controlled data using ClickJacking. This works on JSP applications and partially on ASP.NET applications.

Let us take the case of a simple primary Email ID update form. Such forms are common in many web applications. They are simple but extremely important, if an attacker manages to force a victim to update his primary Email ID with that of the attacker’s ID then the attacker can perform a password reset and compromise the victim’s account.

A sample Email ID update form is given below, this contains a ‘csrf-token’ parameter for CSRF protection:

<form method="POST">
<input type="text" name="email" value=””></input>
<input type="hidden" name=”csrf-token” value="a0a0a0a0a0a"/>
</form>

Let’s say this form is available at 'www.example.com/updateEmail.jsp'
Since this form does not contain an ‘action’ attribute, on submission the form will be submitted to the current URL in the address bar, which will be ‘www.example.com/updateEmail.jsp’.

The source code of 'updateEmail.jsp' would typically look like this:

if ( request.parameter("email").isSet() && request.parameter("csrf-token").isValid() )
{
//process the form and update the email ID
}
else
{
//display an empty form to the user (CSRF token included)
}

The application checks if the request contains a valid CSRF token, if not it displays the form to the user.

Now to submit our sample form using ClickJacking the attacker can include an iframe like this
'<iframe src=”http://www.example.com/updateEmail.jsp?email=evil@attackermail.com”>'

When this request goes to the server the application would display the update form. When this form is submitted by the victim using ClickJacking the request that is sent to the server is like this:

POST /updateEmail.jsp?email=evil@attackermail.com HTTP/1.1
Host: www.example.com

email=&csrf-token=a0a0a0a0a0

Since the form was not filled by the victim, the email parameter in the POST body is blank. However since the action attribute of the form was empty the form is submitted to www.example.com/updateEmail.jsp?email=evil@attackermail.com. Now the QueryString contains the attacker entered value for the ‘email’ parameter.

This request contains two values for the ‘email’ parameter, one in POST body and one in QueryString. Enter HTTP Parameter Pollution, when the server side JSP code calls request.parameter("email"), the value that is returned is the one in the QueryString and not the POST body. Since this value can be controlled by the attacker he can trick the victim in to updating his account with the attacker’s mail ID.

This attack can also work in cases when the form is submitted with JavaScript like this:

<form onSubmit=process()>
<input type="text" name="email" value=""></input>
<input type="hidden" name="csrf-token" value="a0a0a0a0a0a">
</form>

<script>
function process()
{
//check if email is set
form.action = document.location; //document.location will give out the entire URL with parameters
form.method = "post";
form.submit();
}
</script>

Apart from JSP applications, this attack can be extended to ASP.NET applications as well.
However since ASP.NET appends a ‘,’(comma) between duplicate parameters, it not as clean. But there are plenty of areas where having a trailing ‘,’ won’t hurt. In ASP.NET applications the form action is always set by the framework because of the 'runat="server"' attribute. The only requirement now is that the application should make use of Request.Params. Even if the application does not use Request.Params, forms submitted over 'GET' are still vulnerable. So all ASP.NET application using Request.Params or submitting forms over 'GET' are vulnerable to this attack!

Similar attack is also possible on ASP applications where the form element is of the form described earlier and if it is submitted over 'GET'. Like ASP.NET application a trailing comma is introduced here as well. A more detailed description of HTTP Parameter Pollution on ASP and ASP.NET applications and the significance of Request.Params is explained here. This whitepaper discusses how HPP can be used to bypass WAF.

15 comments:

  1. Nice. Just one remark. The IFRAME inclusion is a standard technique for this kind of web attacks. Clickjacking is something different in which the IFRAME is (usually and in simpler attacks) css-rendered transparently and overlaid at the web page in order to trick the user into clicking on elements controlled by the attacker. Maybe you would be interested in a work with a recently conducted on Clickjacking : "A Solution for the Automated Detection of Clickjacking Attacks" - Have a nice day, embyte

    ReplyDelete
  2. Thanks Marco. I do realise that ClickJacking relies on careful CSS rendering. Since I wanted to emphasize on the 'anti-CSRF' technique here, I left out the CSS part in the example's IFRAME for simplicity. I read through your whitepaper, it is a very impressive piece of work and a novel approach. I have some observations. Your 'testing unit' scans through the page for clickable elements and clicks on them. The ClickIDS scans for other clickable elements in the same region and then triggers an alert. Instead cant you simply scan for all clickable elements and look for overlapping units and trigger the alert. That might be much faster and efficient. For the rare cases where sections of the pages are changed based on mouse movements, you can rescan the page. Moreover since FF is used for the testing there is a possibility that some attacks were missed. Because in my limited experience with CSS I have seen differences in how IE and FF align elements. And IE being more popular more attacks would target its users. These could have possibly gone undetected in your assessment. Would like to hear your views on this. Its an excellent academic effort, congrats!

    ReplyDelete
  3. Hi there, I reached your answer for "chance" since blogger did not informed me :) I see the point, actually we could have run the experiments in simulation by detecting overlaps only looking at the elements' coordinates. Btw, we decided to go for the "real clicks" scenario since many applications are pretty complex to analyze for their dynamic behavior (see Javascript/CSS events as you are saying). Moreover, our primary goal was to conduct a study of the prevalence of clickjacking attacks on the web and that's why we employed noScript in its modified version (and to make noScript run we need to physically interact with the page by clicking on the elements).
    Regarding the fact that we used FX to conduct the research you are right. It would be nice to deploy the same system on Explorer, e.g. by running Explorer in Linux with "wine" (the emulator) and porting ClickIDS to Explorer as BHO.
    I am pretty sure that many CSS attacks are tailored for Microsoft and Explorer.
    Note that our findings have been manually tested on Explorer too.
    Great that you like the work.
    Next April there will is a talk at BH Europe on clickjacking, I don't know Paul but hopefully will be interesting.
    Have a nice day.

    ReplyDelete
  4. Hi Marco, I can see that your approach is justified based on what you were trying to achieve. Good luck for your own presentation @ asiaccs2010. Am looking forward to Paul's talk too, should be interesting. Take care.

    ReplyDelete
  5. A temporary fix that could work could be a simple javascript script like this http://www.cryer.co.uk/resources/javascript/script1.htm . Very interesting article. Thank you.

    ReplyDelete
  6. @cedric: right, this is another frame-busting code. Twitter and other sites now already implement that code. In our work, we had run an experiment to assess the prevalence of such sites: ~3.8% = 352 sites. See section 4.3 for more details :)
    embyte

    ReplyDelete
  7. @cedric
    Thanks :) Any defense that prevents ClickJacking will automatically prevent this attack as well.

    @Marcos
    Interesting stats!. Session IDs in the URL or a CSRF token in the URL can also thwart a ClickJacking attack because the URL for the iframe cannot be guessed by the attacker. I dont see anyone talking about it or maybe its lost in the noise about the framebusting-based approach.
    Views?

    ReplyDelete
  8. Warning, PHP-centic comment ahead:

    This kind of thing is why we ended up changing the Zend HTTP Request Object (well, extending and using, not changing) away from its hard preference of GET over POST for getParam(), and molded it into one that reads out the request_order/variables_order INI settings and behaves accordingly.

    In nine out of ten cases, I'm a fan of aggregating request parameters in some way, since it helps defeat an unfortunately still wide-spread belief that making something POST means it can't be hacked 'anywhere near as easily', and forcing people to deal with all incoming methods hones their security sense a bit more - but prefer-GET-over-POST is definitely broken in so many ways. *always changes this*

    It's especially evil in Zend, actually, since by default if you manage to get someone to pollute their GET-parameter space on one page, Zend's url() Action Helper will drag that along to other pages - i.e. it wouldn't help if you had a <form action="<?php $this->url('controller' => 'your-controller', 'action' => 'your-action'); ?>"> in that script.

    (We changed that with our own version, too.)

    *shudders* Nightmare.

    ReplyDelete
  9. ...ohduh. Sorry. url() View Helper. Been working with Action Helpers too often lately.

    ReplyDelete
  10. @pinkgothic
    thanks for the info. I have never used zend so I dont know how it works there. AFAIK in PHP POST data takes precendence over GET, which is the exact opposite of JSP. So I dont think this attack can work against it. However I have never used zend, are you saying this attack works on zend? that would be intresting

    ReplyDelete
  11. I found this post a bit late, but interesting reading nonetheless.

    Maybe a viable counter-measure to this kind of attack is to implement a request filter that checks:

    1. Presence of the CSRF token
    2. If token present, check if form was submitted via POST
    3. Check for the presence of query parameters on the request URL

    If any of those checks fail, the requested action would be denied.

    ReplyDelete
  12. @anon
    Thanks.
    What you have suggested would actually work but that may not be necessary. If you implement strong Clickjacking protections in your application then this vector is automatically taken care of.
    If you block this vector without Clickjacking protection then CSRF can still happen using the HTML5 Drag-n-Drop API, its a little bit more tedious to pull off when compared to this though.

    ReplyDelete
  13. Each and every post of the form The CSRF token should be checked, it hepls us in protecting the evil form submission.

    ReplyDelete
  14. Hello there..................

    i m a begginer.............
    for this i will hav to create a website?
    and then upload these scripts?

    ReplyDelete