Pwning Yr Form with Firebug

posted on Thu, Sep 2 2010 12:00 am by Selah Ben-Haim

So you've decided to put a form on your website. Congratulations, you've taken your first foray into the collaborative world of the social web! And commendations on your bravery, because soliciting user input is by far the most reliable way of introducing security vulnerabilities to your site.

A unique issue for web applications is that, unlike their desktop counterparts, the UI of your website serves only to suggest how users may interact with the cogs that turn beneath. And unfortunately for you, the cunning hacker cares little for your meticulously coded select lists, check boxes, and hidden fields. Your interface is proverbial putty in the hands of this unsavory specimen, and in this post, we'll explore one simple way such abuses are accomplished.

Enter Firebug. Firebug is an incredibly useful plug-in for Firefox, designed to give web developers the ability to mess and mangle with the pages they're developing.

It can also be used to wreak havoc on sites that don't properly sanitize incoming data.

Now, before we go any further, I want to be sure you don't get the wrong impression of Firebug. This is not a hacking tool. Firebug is a godsend to workaday web monkeys like you and me, and the hack-tackery I'm illustrating in this post can be achieved using the developer tools that come with almost all modern browsers. (You don't even want to know what the hacker bon ton can pull off using command-line tools like curl and wget.)

Enough jibber-jabber, let's take a look, shall we? Here's the source for a simple form:

<form method="post" action="/">
<p>
<label for="name">Name</label>
<input type="text" name="name" id="name" value="" />
</p>
<p>
<label for="friend-or-foe">Friend or foe?</label>
<select name="friend-or-foe">
<option value="friend">Friend</option>
<option value="foe">Foe</option>
</select>
</p>
<p>
<input type="submit" value="Pwn" />
</p>
</form>

And here's how it renders out:

simple form

Anyone who's been around the web long enough to cherish memories of their erstwhile Geocities account knows that text fields are SQL injections waiting to happen.

Little Bobby Tables is out there and salivating over the thought that you may be trustingly transcribing whatever he types into that little box directly to your database. Of course, you're too smart for that.

But what about the select list? Seems safe enough. After all, what could result other than "Friend" or "Foe"?

Let's fire up the 'Bug.

And let's wreak some havoc.

Uh oh.

Defending against this sort of attack is simple, you just have to bother about doing it.

In this case, we know exactly what sort of input we're after, so we can be very specific about what we'll allow.

if (  $user_input === 'friend' ) {
write_to_db( $user_input );
extend_warm_welcome();
}
else {
write_to_db( 'foe' );
treat_with_due_hostility();
}

This hard-lined approach to validation trumps any amount of input escaping because it leaves exactly zero room for connivery.

It's generally a good security practice to provide as little slack as possible in your code.

Here's an even more troubling example.

<form method="post" action="/">
<input type="hidden" name="member_id" value="1" />
<p>
<label for="password">Password</label>
<input type="password" name="password" id="password" value="" />
</p>
<p>
<label for="password-confirm">Confirm</label>
<input type="password" name="confirm" id="confirm" value="" />
</p>
<p>
<input type="submit" value="Pwn" />
</p>
</form>

Your hidden declaration means little to your enemies.

You can avoid this scenario by keeping the member ID out of the hands of your visitor in the first place.

Store it in a session, and it's safe from meddling fingers. (That is, so long as your sessions are safe from hijacking.)

The lesson you should be taking away is that any value that's represented in your form is fair game for tampering.

And while forms make especially enticing targets for the ne'er-do-wells about the web, keep in mind that these manipulation techniques apply to anything that resides on the client side of the client-server love affair. Query-string parameters, JavaScript, even browser cookies are vulnerable.

I'll leave you with a little story about a no doubt well-meaning site that offered a shopping cart service. It was simple and flexible: You, the retailer, set up a form containing text fields where visitors may enter the quantities of items they're purchasing. Alongside these are hidden fields that hold the prices of those items. The form posts directly to the cart site, which produces the appropriate shopping cart.

And what do you supposed happened when I changed the hidden price field of some rather expensive items to, say, $0? Now what now do you suppose happened when I set the price to a negative value? You guessed it: I got rich, retired early, and moved to the Cayman islands where I spend my leisure time writing articles about web application security.

blog comments powered by Disqus