Friday 1 May 2015

Whitelisting - a Paler Shade of Security

URL parameters are an easy and convenient way for web pages to pass data to other pages. And, where SEO is concerned, it's a plus because URLs can be cached. But sometimes it can be too convenient. People tend to forget that such methods are open to abuse and appropriate measures can (and should) be taken against said abuse.

Below are some instances of URL parameters, where products is the page name, and id and type are the parameters, and "34400" and "cars" are their respective values.

products.php?id=34400&type=cars
products/cars/34400

Obviously, some of the security risks are SQL Injection and XSS. I'm writing this with the assumption that you know what that is, and on the off-chance that you don't, check out an explanation of SQL Injection and XSS.

There are plenty of ways to deal with such threats, some at script level (depending on language), some at database level (depending on database). But these aren't under discussion today, because there is a simple and non platform-specific solution at the logical level: whitelisting.

What's Whitelisting?

Whitelisting is a technique that ensures that the values of the parameters conform to a specific range of values. At its simplest, here is a preliminary example. (All examples are in PHP)

URL: products.php?id=56700
<?php
$productid = $_GET["id"];
$productid = intval($productid);
?>

The above example ensures that the variable productid, when taken from the URL, is an integer, by converting the value of productid to its integer equivalent. With this, it's not possible to enter malicious code into the parameter, and the usability of the data is preserved. If I wanted to be pedantic about this, the above could be termed sanitization instead of whitelisting.

To take this further and to see a more comprehensive example of whitelisting, see the following.

URL: report.php?month=11&year=2011
<?php
$reportmonth = $_GET["month"];
$reportmonth = intval($reportmonth);

if ($reportmonth<1) $reportmonth=1;
if ($reportmonth>12) $reportmonth=12;

$reportyear = $_GET["year"];
$reportmonth = intval($reportmonth);

if ($reportyear<1969) $reportyear=1969;
if ($reportyear>year(date)) $reportyear=year(date);
?>
See what went on there? The variables reportmonth and reportyear were forced to conform to a range of values. reportmonth had to be a value from 1 to 12. reportyear had to be a value from 1969 to the current year. This makes it impossible for the values to do any damage if written as part of an SQL string.

What if input is a string? 

Well, in that case we can't convert the value to integer. But, we can still make input conform via an array. URL: products.php?type=cars
<?php
$producttype = $_GET["type"];

$wl_producttype = array();
$wl_producttype[] = "buses";
$wl_producttype[] = "cars";
$wl_producttype[] = "vans";
$wl_producttype[] = "lorries";

if (!in_array($producttype,$wl_producttype)) $error=true;
?>

With this, we ensure that the value of producttype is either "buses", "cars", "vans" or "lorries". All else produces an error.

What if there's no range to conform to? 

That can happen, yes. If, for example, the parameter is a search string and thus can theoretically be any value, then there's no conformity to speak of. Therein lies the limitation of whitelisting. Simple and elegant, but applicable only to very specific instances such as those outlined.

Why go to that trouble, then?

You'd be surprised, though, how many web developers don't bother with this, hoping that more advanced techniques will catch any monkey business. I think that's terribly short-sighted. It's good to secure your code at a logical level to weed out any possible exceptions before letting more advanced security techniques do their job.

messagetype=goodbye&article=whitelisting
T___T

No comments:

Post a Comment