Didn't see this anywhere and I thought it may interest some people. Goes to show you should always sanitize all user input.

Code Injection via Hidden Form Field Manipulation

Date: 5/17/2006

Author: Monte Toren

mtoren (at) AlertPool (dot) com [email concealed]

http://www.AlertPool.com (Security Alert Aggregator)

* Systems Affected:

Potentially any website that passes user supplied data via a hidden form field element.

* Overview:

This paper shows a simple technique for injecting code by manipulating hidden form fields.

Best practices for web development clearly dictates that user supplied input should always be sanitized for dangerous characters (such as '>') to avoid code injection in dynamically generated pages (see http://www.cert.org/advisories/CA-2000-02.html). However, what might not be as clear is that this sanitization must be done before any data is passed in a hidden form field. Since hidden form fields do not display in the browser, developers may feel safe passing unsanitized data in them (to be sanitized later). This practice is not safe, as will be shown.

Please note that I am not claiming to have discovered a new vulnerability here - I am simply highlighting a specific case of an existing vulnerability that might be less than obvious. I ran across this when auditing a real site, so I know sites have actually made this mistake.

* Description:

Imagine a web page that accepts user supplied input, but does not sanitize it before passing that data in a hidden form field. Perhaps the sanitization isn't done until later. An example might be a multi-page sign-up flow, where the username is passed from page to page, not to be displayed again until the final confirmation page. In this case, the developer may feel safe not sanitizing the data until being displayed on the confirmation page. Another possibility is that the page passes the data to an external script that does the sanitization via a hidden form field. Whatever the reason, any dynamic page that passes unsanitized data via a hidden form filed is potentially vulnerable.

* Examples:

The dynamically generated HTML for passing a user's name from one page to another with a hidden form filed looks something like this (where value is what the user entered - i.e. "Joe User".


<input type="hidden" name="username" value="Joe User" >


But what happens if the user enters " > Joe User (double quote followed by greater than then their name) for their username?

The above code now looks like this:


<input type="hidden" name="username" value="" >

Joe User">


We now have an empty value (since we ended the quotes), then we end the hidden tag by supplying the end '>'. We have Joe User "> as a line of HTML that will be output to the user's browser, despite the fact that it is hidden. To make this cleaner, we just need to insert a HTML tag that ends in ">, to get rid of the trailing ">. One such tag is the anchor tag.

So if we enter " > Joe User <a name="

The dynamic code now becomes:


<input type="hidden" name="username" value="" >

Joe User

<a name="">


Now the browser will just display "Joe User" without the trailing ">. The <a name=""> tag is just there to take up the ">, and doesn't change the output in the browser.

But Joe User isn't very interesting, what if we were to insert code instead? Using the above technique, the following value entered by the user and passed to a hidden form field will display their cookies:

"> <script>alert(document.cookie)</script> <a name ="

The dynamic code now becomes:


<input type="hidden" name="username" value="">


<a name ="">


At this point, we can inject any code between the "> and the <a name=", such as inserting an iframe to a site that steals login info, or code to post cookie data to a malicious site, etc.

But what if value isn't the final argument in the hidden field? What if they coded such as this?


<input type="hidden" value="Joe User" name="username">


We use almost the same technique. For example, we could enter

" > Joe User <a

and get the following code:


<input type="hidden" value="" >

Joe User" <a name="username">


* Solution:

Never pass unsanitized data in a hidden form field.