Mama Says $_REQUEST is the Devil

And unlike her embarrassing mistake with the alligators, this time Mama is right.

To those unfamiliar, PHP makes available something called super global arrays that allow you to access various things, server properties ($_SERVER), cookies ($_COOKIE), post and get values ($_POST, $_GET), etc.

When you submit a page that looks like this:

http://localhost/foo.php?key=value

Your variable is available in the $_GET superglobal array. You can access it with $_GET['key']

Likewise, when you submit a form via post, you can get the form values from $_POST the same way.

$_REQUEST, however, is the grandaddy of them all, allowing you to access all of the POST, GET, and COOKIE values from one array. How convenient, right? How very courteous, to make an array I can grab anything from at any time I want. Lovely, right?

Wrong. Really wrong. Really, really, really wrong. $_REQUEST is the same thing as using register_globals to handle GET and POST. It allows anything and everything you have to be hacked given very little knowledge of your actual application internals.

For example: Let’s say you have a web application with a front-end and an administration panel. You only want people with admin rights to be able to access the admin panel, most likely, so you build yourself a little login panel, and a form, which posts to a script the variables username and password. Those are then checked against the database, and boom, you’re in business, knowing who to authorize and who not to.

That code would look something like this:

$username = $_POST['username'];
$password = $_POST['password'];

$result = mysql_query(”select id from admin where username=’$username’ and password=’$password’”);

if (mysql_num_rows($result))
{
$_SESSION['admin_access'] = TRUE;
$_SESSION['admin_id'] = mysql_result($result, 0, “id”);

}

(The code above is far over-simplified and only used as an example. I recommend error checking, good connection management, and database framework classes. Don’t code like this.)

Now then, the problem with using $_REQUEST['username'] instead of $_POST['username'] in the example above is this: I can hack you in 2/10s of a heartbeat. Literally. Let’s call this script “login_check.php” for giggles. Hitting the following URL would compromise access to your administration panel:

logincheck.php?username=foo’%20or%20true%20–

Because you’re using $_REQUEST instead of the right array, username is going to be populated with the value I entered in the url, not what you thought it was going to be populated with. So, the query you thought you were executing now looks like this:

mysql_query(”select id from admin where username= ‘foo’ or true –’ …);

And since MySQL sees everything after the two dashes as a comment, guess what? That query will ALWAYS return records, meaning that hitting it with that url will always log someone in as an administrator.

It’s called SQL injection, and if you’re using $_REQUEST or register_globals=On, you’re asking for it to happen. Begging for it, even.

I could go on and on, but if you read this far into the piece, you care enough about your code and your professional reputation not to use $_REQUEST or register globals. And if you don’t, you may never regret it, and someone will come hire me to clean up your mess later. Fine by me.

~A!

WordPress Themes