The addslashes() Versus mysql_real_escape_string() Debate

by Chris Shiflett

Related link: http://shiflett.org/archive/184



Last month, I discussed Google's XSS Vulnerability and provided an example that demonstrates it. I was hoping to highlight why character encoding consistency is important, but apparently the addslashes() versus mysql_real_escape_string() debate continues. Demonstrating Google's XSS vulnerability was pretty easy. Demonstrating an SQL injection attack that is immune to addslashes() is a bit more involved, but still pretty straightforward.


For the impatient, here's the code:


<?php 

$mysql 
= array();

$db mysqli_init();
$db->real_connect('localhost''myuser''mypass''mydb');

$_POST['username'] = chr(0xbf) .
                     
chr(0x27) .
                     
' OR username = username /*';
$_POST['password'] = 'guess';

$mysql['username'] = addslashes($_POST['username']);
$mysql['password'] = addslashes($_POST['password']);

$sql "SELECT *
        FROM   users
        WHERE  username = '{$mysql['username']}'
        AND    password = '{$mysql['password']}'"
;

$result $db->query($sql);

if (
$result->num_rows)
{
    echo 
'<p>Success</p>';
}
else
{
    echo 
'<p>Failure</p>';
}

?>

The full explanation covers this in a bit more detail, but the basic idea is that addslashes() can be tricked into creating valid multi-byte characters out of invalid ones. Whenever a multi-byte character ends in 0x5c (a backslash), an attacker can inject the beginning byte(s) of that character just prior to a single quote, and addslashes() will complete the character rather than escape the single quote. In essence, the backslash gets absorbed, and the single quote is successfully injected. This opens the door for SQL injection attacks.


The moral of the story is to use mysql_real_escape_string(), bound parameters, or any of the major database abstraction libraries.