2009
07.07

There are…

Two ways of injecting SQL. Either via URL, or form fields.

Surely you’ve noticed web address’s like www.site.com/script.php?item=1

There are many methods of injecting SQL. The $_GET variable is a more vulnerable aspect than $_POST. It always will be, due to the user’s ability to see the variables so easily. Sure, there are secure ways of using $_GET; Mostly in a switch/case scenario where unknown variables won’t be executed, and/or revert to a different page.

Before running through any data retrieved from the URL, one should cleanse them. For example, let’s say you have something like this:

1
$item = $_GET['item'];

A few ways you could secure it:

One

The simplest way would be to assess how many items you have in the database. Let’s say you have 300 items, you would therefore never need to use more than three digits to identify it. Now, we’ll add this:

1
2
3
4
5
if(strlen($_GET['item']) <= 3) {
	$it = $_GET['item'];
	} else {
		$it FALSE; header('Location: error.php');
		}

That isn’t perfect, but it is a step in the right direction. Especially if you’re starting from scratch.

Two

What else do we know about how the items are identified? We know they’re numeric, of course, so an alpha character will never be needed. So, let’s make sure the value is numeric, so we can avoid funky characters / charsets being run through.

1
2
3
4
5
if(is_numeric($_GET['item']) && ($_GET['item']) <= 3) {
	$it = $_GET['item'];
	} else {
		$it FALSE; header('Location: error.php');
		}

This adds yet another layer to the security of the application. The is_numeric() function assures that only numeric values go through, so we can avoid strings such as: ?item=’;DROP TABLE stuff or ?item=”>wut?

The former could lead to an SQL injection, which would delete the table with your stuff, the latter could lead to an XSS issue.

Three

We know we have 300 items. How does this help? Well, you can ensure that the number fals within a certain range. How do we do this? Add “quotes” to our previous code, like so:

1
2
3
4
5
if(strlen($_GET['item']) <= "300") {
	$it = $_GET['item'];
	} else {
		$it FALSE; header('Location: error.php');
		}

This still isn’t quite perfect, but it’s another layer, and you have some rules applied for asigning values.

In an ideal situation, you don’t want to use $_GET to directly retrieve data, ever.

$item should be a variable, no more, no less. In proper, secure design, $item wouldn’t be able to communicate with the database directly from the URL. It happens a lot, but it doesn’t make it any more acceptable. I’m sure professional developers may disagree.

A general idea of what you’d want to use is kinda like this:

1
2
3
4
5
6
7
8
if(strlen($_GET['item']) <= 3) {
	$it = $_GET['item'];
	} else {
		$it FALSE; header('Location: error.php');
		}
if($it){
	$q = 'SELECT item_id FROM store WHERE item_id = '.$it;
}

This is a poor example, and I don’t advice to apply the actual code, just the principles that come along with it. Have fun.

3 comments so far

Add Your Comment
  1. PS: All the &a­mp and &l­t; parts are supposed to be the characters they represent, I’m not sure why it’s being parsed like that.

You must be logged in to post a comment.

Easy AdSense by Unreal