Friday, September 28, 2012

Cross-Site Request Forgery against applications that use JSON RPC

Cross-site request forgery is common and well known web application vulnerability. Most of the time exploiting these vulnerabilities is relatively straightforward. You just need to set up a proper HTML form or even use a simple URL. Sometimes, however, things can get a little more complicated. One such example is when the targeted application is using JSON-RPC.

JSON-RPC is a simple mechanism for issuing a remote procedure call using JSON notation and HTTP. When issuing a JSON-RPC request browser will send a POST request to some URL and the body of the request will be a JSON encoded data, like this:

{"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}

More on JSON-RPC can be found here

Now, the problem is how do you create a CSRF attack against an application that is expecting these kinds of POST requests. Using Ajax (XMLHttpRequest) will not help you since the browser will check for permission to do a cross-domain request (using OPTIONS request).

We at DefenseCode would like to share a little trick that we use in our penetration tests. You can use this trick to construct an HTML form that will force the browser to submit a proper JSON RPC request to the target application.

Problem with HTML forms is that input elements need to have a name, without a name, browser will not send the data even if you specify value of the element. To get around this you can set only the name of the input element without a value. For example:

<input name="test_name" />

Browser will send "test_name=" (without the quotes) to the server. Now, if you could set the name of the element to the body of the JSON-RPC request browser will send it. Since the body of the JSON request contains special characters you should put it inside an HTML using single quotes or you can use a little JavaScript, like this:


function modifyForm() {
    document.forms[0].elements[0].name = "{\"jsonrpc\": \"2.0\", \"method\": \"subtract\", \"params\": [42, 23], \"id\": 1}"; return true;
}
<form name="csrf_form" method="POST" action="https://example.com/rpchandler" onsubmit="modifyForm();">
    <input name="test" />
    <input type="submit" />
</form>


This form will cause the browser to send the JSON-RPC data in the body of the POST request to our target URL (with an equal sign on the end). Only one little problem remains. By default browser will urlencode the body and this will break the JSON-RPC parser. To get around that we can use the enctype="text/plain" attribute in the form. text/plain will cause the browser to skip urlencoding. It will only turn spaces into + signs, but luckily we don’t need spaces in JSON :) So, our form for attacking a JSON RPC web application will look like this:


function modifyForm() {
    document.forms[0].elements[0].name = "{\"jsonrpc\":\"2.0\",\"method\":\"subtract\",\"params\":[42,23],\"id\":1}";
    return true;
}
<form name="csrf_form" method="POST" action="https://example.com/rpchandler" enctype="text/plain" onsubmit="modifyForm();">
    <input name="test" />
    <input type="submit" />
</form>

7 comments:

  1. typepad has such vuln btw http://homakov.blogspot.com/2012/06/x-www-form-urlencoded-vs-json-pros-and.html

    ReplyDelete
  2. How can we also remove that "=" at the end?

    ReplyDelete
  3. Truyen ngon tinh hay la the loai truyen tinh cam
    Truyen teen hay la nhung truyen tinh yeu tuoi teen
    Don doc tai trang doc truyen online.

    ReplyDelete
  4. The article you have shared here very good. This is really interesting information for me. Thanks for sharing!
    hotmail login |hotmail sign in |free hotmail login

    ReplyDelete