Offensive Thinking

Internet Thoughtcrime

xsrfify: XSRF Helper Script

Posted: 2010-02-28

Cross Site Request Forgery ([X|C]SRF) is one of those vulnerabilities many web applications suffer from. If you already know how XSRF works, I suggest you skip the next part and directly go to the explanation of xsrfify.rb, a script to automatically convert a POST request to an HTML page ready for XSRF.

XSRF explained

The idea of XSRF is as simple as it is ingenious. Let me explain by example: Let’s say you have a web application which requires a login. A logged on user can also change his or her password, which is done by sending a simple POST (or even a GET) request to the application. The password change request could e.g. be done with this simple form:


Please enter your new password:<br />
<form method="POST" action="changepw.php">
  <input id="pass" type="password" />
  <input type="submit" value="Submit" />
</form>

Now, here’s the deal: as an attacker, you don’t have the login credentials, so you can’t just go and change the password. Instead, you do the following: You create an HTML page like the above, but instead of showing the form you hide the input fields. And instead of adding a submit button, you add a little bit of JavaScript to automatically submit the form whenever someone visits your HTML page. This may look like the next snippet:


<html>
  <head>
  <script type="text/javascript">
    function send() {
      if (document.forms[0]) {
        var el = document.getElementById("submitform");
        el.submit();
      }
      else {
        setTimeout("send()", 1000);
      }
    }
  </script>
  </head>
  <body onload="send()">
  <form method="POST" id="submitform" action="http://www.example.com/changepw.php">
    <input id="pass" type="hidden" value="desired_password" />
  </form>
  </body>
</html>

Notice how the action parameter of the form now contains the full path to the PHP page, because we are hosting this web page on our own server and the victim’s server is on http://www.example.com (that’s where the cross site in XSRF comes from). Notice also how the little JavaScript snippet gets called immediately by the onload() handler in the body tag and submits the form (or waits a second if the element is not yet loaded).

The result is, whenever an unsuspecting user opens your website, a POST request to the password-changing PHP page is sent. But that’s not the important part. The important part is that your browser, whenever it sends a request to the site while you are still logged in to the application (e.g. in another tab in your browser), the login credentials will automatically be sent with the request. Because, hey, it’s just another POST request to the website we’re logged into, right?

This means that if you are logged into the application and I can convince you to open my (malicious) website, I can make you send a request to change your password. Without knowing any login details. Because it’s your browser sending the request, and you are already authenticated. The password example above is only one possible attack vector, of course. Just look for anything in the web application which changes something using only one request. There’s plenty of XSRF opportunities for doing something malicious.

xsrfify.rb

Ok, so I got a bit carried away explaining XSRF, because my original intent was to announce a little tool I made for facilitating the exploitation of XSRF. You see, writing HTML pages like the above, to automatically send a POST request, is kinda boring. It’s always the same. A little bit of JavaScript code, a form with all the parameters, the full path to the web site. This can easily be done with a script. So I wrote xsrfify.rb. It’s little Ruby script which you can throw a raw POST request at on STDIN, and it will turn it into an HTML site with a form automatically submitted via JavaScript, ready for XSRF. Simple as that. The options are:


./xsrfify -h
Usage: ./xsrfify [options]
 -n, --newlines        Use \n as line delimiter when parsing the POST request instead of \r\n
 -f, --full-page       Print a full HTML page ready for XSRF instead of just the form
 -d, --delete-submit   Automatically delete parameters with the name "submit"
 -h, --help            Show this help

Beats writing the same old boring stuff over and over again. By the way: it works great for Cross Site Scripting only exploitable via POST, too. Just make sure that you encode your payload properly, as the script will not care about it. Just change stuff in the resulting HTML page accordingly, otherwise things may break (e.g., if you have double quotes in your payload).

It is available on github as of now:

http://www.github.com/courts/snippets/tree/master/xsrfify/