June 16, 2006

PHP form input and Cross-Site attacks

You will find other articles relevant to this document in these sections:
Cameron Manderson @ 11:51 am

Something that we have to be careful to consider is hackers generating a Form and remotely sending form input to your website. eg.

  1. Hacker creates a form that has the same variables as your website form, and sets the action to your websites form action;
  2. Hacker hits submit to inject in values to your form; such as malicious code or generating a script that automatically inserts data

Although we learn never to trust information sent to us in a form and checking the submitted values to be valid, we will also want to consider the origin of the forms submission [Cross-Site Request Forgeries (CSRF)]. Our Environment variables allow us to check a variable called HTTP-REFERRER but this can be easily changed by the hacker. So instead we will need to consider ways to ensure the form originated from our website (and only issued once).

I have done a little research into ways and Chris Shifflet recommends a token placed into the form and applied to the users session. This method can prove a very useful method of identifying whether a form had been “issued” from your website. His example of a useful way to help limit the occurance of this issue:

<?php
$token = md5(uniqid(rand(), true));
$_SESSION[‘token’] = $token;
$_SESSION[‘token_timestamp’] = time();
?>


<form action=”/add_post.php” method=”post”>
<input type=”hidden” name=”token” value=”<?php echo $token; ?>” />
Subject: <input type=”text” name=”post_subject” />
Message: <textarea name=”post_message”></textarea>
<input type=”submit” value=”Add Post” />
</form>

Chris’s recommendation supplies quite a good method of forcing the use of your own HTML forms, but is linear in nature (one form with one submit). For this to be more rock solid we need to consider implementation issues we always face as Web Developers: Multiple Windows and the Back Button.

We can make some more modifications to the script by including a 2D array of issued form tokens, and individually identify the Form with the corresponding Token:

<?php
$formId = md5(uniqid(rand(), true));
$token = md5(uniqid(rand(), true));

$_SESSION[‘formTokens’][$formId][‘token’] = $token;
$_SESSION[‘formTokens’][$formId][‘token_timestamp’] = time();
?>

<form action=”/add_post.php” method=”post”>
<input type=”hidden” name=”formId” value=”<?php echo $formId; ?>” />
<input type=”hidden” name=”token” value=”<?php echo $token; ?>” />
Subject: <input type=”text” name=”post_subject” />
Message: <textarea name=”post_message”></textarea>
<input type=”submit” value=”Add Post” />
</form>

We now are able to uniquely identify the valid token based on a unique form ID, with its own timeout values etc. This will allow us to cater for multiple windows or use of the back button across our forms.

Share and Enjoy:These icons link to social bookmarking sites where readers can share and discover new web pages.
  • del.icio.us
  • digg
  • Furl
  • Reddit
  • YahooMyWeb

4 Comments »

  1. Also you might want to unset the formId from your session when it is sumitted to the server. Also you will want to consider a strategy for your token_timestamp, which you can now use to make forms expire.

    Comment by Cameron Manderson — June 16, 2006 @ 1:39 pm

  2. For those reading this article you might also want to read up on my post on mail-header injection, and another method spammers use to “hijack” your mail forms.

    Comment by Richard Lee — June 17, 2006 @ 3:34 pm

  3. […] Content restrictions was never designed to stop basic CSRF, unless you are talking about functions that could only be affected by JavaScript, which would inherantly be stopped.  Brian’s comment that this would not help with reflected JS should be innaccurate, as any JavaScript would be affected (part of the problem was that it could end up killing valid JS on the page, which was something we were attempting to overcome in our first iteration of the idea by wrapping the possible offending output in tags to be parsed out by the browser as safe content). […]

    Pingback by ha.ckers.org security lab - Archive » Content restrictions and script keys — June 27, 2006 @ 2:46 am

  4. as a relative newbie to all of this, I have found this very interesting. So, excusing my ignorance, once the variables have been instantiated on the mail form, how would one verify this on submission?

    Comment by chris — October 17, 2007 @ 10:39 pm

RSS feed for comments on this post. TrackBack URI

Leave a comment