Archive

Posts Tagged ‘get vars’

Handling Foreign HTTP Variables

December 19th, 2008
Comments Off

I have been asked several times about various ways to secure e-commerce applications and other systems from unexpected or badly formatted POST/GET variables. This is a common issue as many developers only develop for the expected and test their application accordingly. Developing for the unexpected can be a bit tricky.

I’ll try to address this issue generically enough that it can be useful to anyone who has a similar issue. I’ll show examples using PHP, however, this process can also be implemented in a similar way using any similar language.

Scenario: You have a small shopping cart that you built for a client and have recently found out that one of the client’s customers had found a way to submit incorrect data to the shopping cart by saving the HTML form page to his computer, then modifying some of the values, and sending the form from his computer. This allowed him to add more options to his product and also lower the price at the same time. Your system didn’t check for anything like that, so you didn’t find it until last week, a whole month later, when you noticed the purchase price in the database was drastically different.

There are a few things you can do to safeguard your application against this kind of problem.

First, you need to make sure that the request comes from a page that is on the same server as the application receiving the request by comparing the referring domain, or you can even go the level of checking the page it came from as well.

Example of domain validation in PHP with Apache:

1
2
3
4
5
6
7
8
// regex match to find referrer "www.domain.com"
preg_match("/https?://([a-zA-Z0-9\-\.]+)/", $_REQUEST['HTTP_REFERER'], $matches);

// check if referrer domain is the same as local
if($matches[1] == $_SERVER['SERVER_NAME'])
{
    // continue processing
}

The previous example verifies that the referring domain IS actually the application domain. You can’t just do a check to see if the server name exists in the referrer, as that can be fooled as well. If the referrer is http://www.mydomain.com/yourdomain.com/hack_you.php, the following would allow the referrer to pass and send invalid data.

1
2
3
4
if(strpos($_REQUEST['HTTP_REFERER'], $_SERVER['SERVER_NAME']) > -1)
{
    // continue processing
}

Second, it’s bad practice to pass anything as a form field value if you can reference using a database id instead. In other words, if a price is associated to a product in a database table, don’t pass the price of $10.00, pass the product id (say 342) and reference the price in your code using that id to extract the information you need from the database.

It’s good practice in general to do whatever you can to never expose data that could be harmful if modified. Along with the previous price scenario, you want to keep user data, database config data, product information, etc… out of sessions, cookies, form fields, etc… Use id’s and other types of identifiers to reference the data in your code.

Now, it’s important to understand that anything is hackable if the attacker has enough time and resources, so there is always the possibility that someone could not only spoof your domain, but with enough attention to detail, they could learn id’s and other values that you are passing them and find ways to send them or modify them in transit or while doing a domain spoof. If your database table structure is setup right and you have guarded against SQL injection (which is a whole separate topic), if id 342 is being passed in your program and they change the id to 549, when your program queries 549 in the database, it should find the appropriate price and associated information. In contrast, if you pass multiple variables in association with one product, changing one of the values, could completely change what you expect to see in your program.

Third, consider creating some tight restrictions on the incoming variables. The first way to do this is to not use the $_REQUEST array, as this allows either incoming POST or GET values. If your form uses POST or GET, you should use the corresponding $_POST or $_GET arrays to access the data. This will limit the ways a hacker can send values into your application as well as lessen the amount of validation you need to do.

In addtion to using the proper incoming array, you can create a variable register that limits the values you expect on that particular page. For example, if you are expecting to see “product_number” and “product_id’ in $_POST, but your application also receives a “price”, you can be sure that someone is sending values to your application that are unexpected. You can either set these values to null, or set flags or logs in your system to notify you that you may have someone trying to manipulate your application.

Checking for unwanted variables in PHP:

1
2
3
4
5
6
7
8
9
10
11
$allowed_vars = array('product_number', 'product_id');

foreach($_POST as $key => $value)
{
    // if not in array of keys, delete it
    if(!in_array($key, $_POST))
    {
        // be careful not to delete vars that may be automatically sent by PHP or Apache
        unset($_POST[$key]);
    }
}

The last thing you’ll want to do with your most important incoming values is verify that limits and values are not out of range and are acceptable. If someone is registering for something and they get free points or bonuses or something, you want to make sure that any variables being sent that contain these values are checked for minimums and maximums, etc… The same can be applied to various other types of values. Just be smart and validate things that your know are crucial to the functionality of your application.

Development, PHP, Ruby , ,



Sponsored Links



agile ajax black hat Cake PHP centering clifford stoll css cuckoo's egg energy energy drinks espionage flash Flex hacker jquery modular MVC objects optimization performance PHP script timer smarty smarty templates stylesheet up-time uptime variable scope web 2.0 Zend Framework