» Birthday Bundle - Over $400 worth of Envato files for just $20

PHP: Sanitize Data to Prevent SQL Injection Attacks

Posted on January 9, 2009, Filled under PHP,  Bookmark it

This is a simple function that sanitizes the data before sending it to MySQL. First it removes whitespaces from the beginning and ending of the string. If magic_quotes_gpc is enabled and the data has been already escaped we will apply stripslashes() to the data. This way the data won’t be escaped twice when mysql_real_escape_string() is called.

function sanitize($data)
{
// remove whitespaces (not a must though)
$data = trim($data); 

// apply stripslashes if magic_quotes_gpc is enabled
if(get_magic_quotes_gpc())
{
$data = stripslashes($data);
}

// a mySQL connection is required before using this function
$data = mysql_real_escape_string($data);

return $data;
}

The function mysql_real_escape_string() escapes special characters in a string for use in a SQL Statement. Unlike the deprecated function mysql_escape_string(), which doesn’t take a connection argument and does not respect the current charset setting, mysql_real_escape_string() calls MySQL library’s function mysql_real_escape_string, which prepends backslashes() to the following characters: \x00, \n, \r, \, ‘, ” and \x1a. It’s strongly recommended to use this function before sending any query to the mySQL database.

Example of unsecured script:

session_start();

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

$sql_query = "SELECT * FROM `members` WHERE username='".$username."'
AND password='".$password."'";

$sql = mysql_query($sql_query);

if(mysql_num_rows($sql))
{
// login OK
$_SESSION['username'] = $username;
}
else
{
$login_error = true;
}

The data sent is not sanitized. Therefore, the user could type anything he wants in the login form. Example:

$_POST['username'] = 'john';
$_POST['password'] = "' OR ''='";

The query sent to the database would be:

SELECT * FROM `members` WHERE username='john' and password='' OR ''=''

This way anyone could login without typing a valid password. The query selects all rows from `members` and the verification with mysql_num_rows() won’t work in this case.

Example of secured script:

session_start();

$username = sanitize($_POST['username']);
$password = sanitize($_POST['password']);

$query = sprintf("SELECT * FROM `members` WHERE username='%s' AND password='%s'",
 $username, $password);

$sql = mysql_query($query);

if(mysql_num_rows($sql))
{
// login OK
$_SESSION['username'] = $username;
}
else
{
$login_error = true;
}

The %s from the sprintf() function indicates that the argument is treated as and presented as a string.

If an attack is made such as the one from the previous example the query sent will be:

SELECT * FROM `members` WHERE username='john' AND password='\' OR \'\'=\''

and will return an empty result set.

Happy coding!

Do you wish to receive the latest updates as soon as they are posted? Get our RSS Feed or Subscribe to the Newsletter!

Get our RSS Feed!

Related Posts

11 Replies to "PHP: Sanitize Data to Prevent SQL Injection Attacks"

  1. I’m going to have to use this. Thanks! But I have to be a smartass and point out the fact that that when sanitized, the code would let john login if his password actually was ' OR ''='. ;)

    1. @Brian Recchia, are you sure? I’ve just checked this and there are no results returned for the query SELECT * FROM `members` WHERE username='john' AND password='\' OR \'\'=\''

    2. Don’t you have any protection on your registration? Are those values not being escaped before being entered into the database?

  2. Was on the hunt for a quick copy and paste sanatize function.

    Whilst I like yours, there is one major issue. It is no reusable.

    What if the user was to use PDO? Or a database other than MySQL?

    Just a heads up :)

  3. Its a good thing you have this. Before I used to have that unsecured coding also and that bothered me a lot when I remember those sites that I have created in the past!

  4. This is my sanitize function in an application where I only expect user input without quotes, double dashes etc. What do you think of it?

    sanitize( &$_GET );
    sanitize( &$_POST );

    function sanitize( &$some) {
    foreach( $some as $key => $value ) {
    $value = str_replace( '--', '', $value );
    $value = str_replace( '/*', '', $value );
    $value = str_replace( '"', '', $value );
    $value = str_replace( "'", '', $value );
    $value = ereg_replace( '[\( ]+0x', '', $value );
    if ($value != $some[$key]) {
    $some[$key] = $value;
    }
    }
    }

  5. This is actually the wrong approach as the only definitively safe method is to use prepared queries. They take a bit more hassle, but really there’s no excuse for doing otherwise.

    1. Yes, they are recommended to use and indeed they take a bit more hassle, but I disagree that my approach is wrong. It depends which option is more convenient to the programmer.

  6. the arguement for the verification of the username should be a case insensitive string comparison.

  7. Hello, I use md5 for my user name/passwords logon

    eg:

    $my_user = md5($_POST['txt_user']);
    $my_pass = md5($_POST['txt_pass']);

    $valid_login_q = "select * from users where md5(user_name) = '$my_user' and md5(user_passw) = '$my_pass'

    The users table is already indexed by a function based index for md5(user_name), do guys think that’s a good idea? I have been used before discovering other methods of “sanitization”.

    See ya..

Leave a Reply


* = required fields

  (will not be published)


XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Note: If you want to post CODE Snippets, please make them postable first!
(e.g. <br /> should be converted to &lt;br /&gt;)