How to Spoof a Form, or Why Your Form Isn’t Safe

Forms can create all kinds of security holes in PHP applications. The biggest reason for this is that you can never be sure just what kind of input you’ll be getting.

There are some steps you can take later on to protect your applications from this unknown input. But first, let’s take a look at why you can never trust a user’s input and just how easy it is for someone to spoof a form.

What Does It Mean to Spoof a Form?

It could mean a number of related things, but generally speaking it means submitting form information in a manner other than the original form was intended. The form processing script, completely unaware of the situation, processes the input as if it came from the original form.

For example, if a form generates a URL query string, one way to spoof that form would be to modify the query string and re-visit the URL. The new page would think that my query came from the original form - even though I really crafted the query myself.

Why would someone want to do this? It may be curiosity. “I wonder what happens if I change this variable…” Or it may be malicious. A hacker can spoof a form processing script to send dangerous input to your PHP script.

The Problem With the “Get” Method

It is easiest to spoof a form if the information is transmitted through the “Get” method. This means that the variables are placed into a query string and appended to the form’s action URL.

Let’s say you have a form with three elements - a textarea element, a hidden input, and a select element. Logically, you might think that the hidden input is restricted to whatever value you set it to and the select element is restricted to one of the options you provided.

To make this a little more concrete, let’s assume the textarea contains a post to a multi-user blog, the hidden input contains the author’s name, and the select element includes the category number.

When the user enters the values and clicks “submit,” he’s sent to a URL that looks something like this.

processing.php?text=Bla+bla+bla&author=Walkere&catid=2

What if I wanted to pretend to be someone else - like Bob? I could simply change the ‘author’ variable.

processing.php?text=Bla+bla+bla&author=Bob&catid=2

Maybe I want to post my message in a special category - one that isn’t normally open to me. Again, it’s as simple as changing the catid variable to another number.

Now, a well designed script will notice these data flukes and either ignore them or spit out an error. However, if you have too much faith in form input - and you blindly used the values from your form - you’d soon be in a mess of trouble.

But Post Is More Secure… Right?

The “Post” method is somewhat more secure. Why? Because all of the information is transmitted behind the scenes.

When I was younger, I tried to meddle with the $_GET variables of an online game that I played. I never would have known enough about the workings of the script to spoof a “post” form - but it was so blatantly obvious with “get.”

However, someone “in the know” can easily spoof a form using the post method as well. One way to do this is… write your own form.

If I look at the HTML source of your form, I can easily see what values you’re submitting to the processing script. I can recreate those input elements on a form on my site - and then set the action to your processing script.

In this way, I could make the hidden and select statements regular text inputs - and input whatever values I want. If you’re form processing script isn’t savvy, my custom values will get passed on to the database.

One thing you can do to prevent this is to check the referring URL coming into your script. This will prevent someone from simply creating a form off-site to spoof your script.

Sending an Actual HTTP Request

The final, and most devious way, to spoof a form is to craft your own HTTP request in PHP. This is essentially what a form does - but you can manually craft the request to your liking instead of letting a form do it.

How do we do this?

First, we create a stream context. To do that we create a simple array and then call the function stream_context_create.

$params = array();
$params['http']['method'] = 'post';
$params['http']['headers'] = 'Referer: http://www.google.com';
$params['http']['content'] = $data; // A regular query string with parameters
 
$context = stream_context_create($params);
 
$fp = fopen($processingUrl, 'r', false, $context);
fpassthru($fp);
fclose($fp);

The actual form values are placed in the $data variable. This is in a typical query string format - key=var&key2=var2, etc. The values should also be url encoded.

The nifty thing here is that you can manually specify HTTP headers to be sent with your request. In this example, we set the referring URL to Google. If someone knew your processing script checked the referrer’s address - they could simply spoof it with an HTTP header.

Never Trust Input

The bottom line is - never trust input that you haven’t thoroughly tested, validated, and cleaned.

Even if an input item is supposed to be hidden or supposed to come from a specific set of values - you can’t be sure that the form processing script is going to receive the correct value. The script needs to check the info and make sure that it got what it was looking for.

It’s pretty simple for someone to spoof your form and send any input they like to your processing script. If you don’t close the security holes, then someone will eventually blow them open for you.


Bookmark and Share:
These icons link to social bookmarking sites where readers can share and discover new web pages.

  • Digg
  • Furl
  • del.icio.us
  • StumbleUpon
  • MisterWong
  • DZone
  • Technorati

Tags: , , , ,

Leave a Reply