SQL Injection

From SecurePHPWiki
Jump to: navigation, search

Example

Do not trust browser defined variables to properly escape special characters.

$query = "SELECT * FROM users WHERE username='" . $username . "' AND password='" . $password . "'";

// the record_exists function is defined elsewhere
if (record_exists($query))
{
  echo "Access granted";
}
else
{
  echo "Access denied";
}

The SQL statement can be modified in a malicious manner to allow logging in as an administrator.

check.php?username=admin&password=a%27+OR+1%3Di%271

Translates to:

password='a' OR 1='1'

This can be thwarted by using the configuration variable magic_quotes_gpc. However, magic quotes only applies to GET, POST, and cookie data. It does not protect against data retrieved by other means (files, database records, etc.).

It is possible to bypass magic_quotes_gpc, so do not rely on just magic_quotes_gpc alone.

Content Control

Variables should be checked for their content to ensure the content is appropriate. Use addslashes to properly escape special characters.

The the passwords (user input and database entry) can also be compared in PHP after the database query. (remember to always store passwords hashed in the database).

/*
password is encrypted with md5 in database, and 
database-query/fetch is already done....
*/

//tell the script to die to avoid confusing if-loops
if ( $recordset[0]['password'] != md5($password) )
{
   die("Access denied.");
}

echo "Access granted.";

Database Abstraction Layer

Another option is to use a Database Abstraction Layer such as what PEAR provides and prepared statements which will properly quote/escape values.

$db = new db();

$sth = $db->prepare('SELECT * FROM users WHERE username=? AND password=?');
 
$result = $db->execute($sth, array($username, $password));

External Information