Search code examples
phpsecuritysql-injection

Does eliminating dangerous characters avoid SQL-injection?


Avoiding SQL-injections there are many ways How to prevent SQL injection in PHP?.

The question is, how is it possible to sql-inject through removeBadCharacters?

function removeBadCharacters($s)
{
   return str_replace(array('&','<','>','/','\\','"',"'",'?','+'), '', $s);
}

It tries to throw out dangerous characters (the application doesn't need those characters):

$x = removeBadCharacters($_POST['data']);

mysql_query("insert into table (x) values ('".$x."');");

// or

mysql_query("select * from into where name = '".$x."';"); 

Solution

  • To be able to inject arbitrary SQL from the context of a string literal, that string literal needs to be left. This is only possible by introducing a string end delimiter, in this case a single ', or by expand the a string literal to a preceding ', e.g., by using the escapes character \:

    $a = '\\';
    $b = ' OR 1=1 OR ';
    $c = ' --';
    
    $query = "SELECT * FROM t1 WHERE a='$a' AND b='$b' AND c='$c'";
    // result:
    // SELECT * FROM t1 WHERE a='\' AND b=' OR 1=1 OR ' AND c=' --'
    //                          \_________/           \_______/
    

    Now as your function removes any ' and \, it seems to be impossible to leave or expand the string literal and thus not possible to inject arbitrary SQL.

    However, since your function does not take the actual character encoding into account, it is possible to exploit this if the MySQL’s character encoding is GBK, similar to how it can be exploited when using addslashes instead of mysql_real_escape_string:

    $a = "\xbf";
    $b = " OR 1=1 OR ";
    $c = " --";
    
    $query = "SELECT * FROM t1 WHERE a='$a' AND b='$b' AND c='$c'";
    // result:
    // SELECT * FROM t1 WHERE a='縗 AND b=' OR 1=1 OR ' AND c=' --'
    //                          \_________/           \_______/
    

    So to play safe, use mysql_real_escape_string or other proven methods to prevent SQL injections.