Question

in documentation of mysql_real_escape_string() it say:

...,taking into account the current character set of the connection so that it is safe to place it in a mysql_query()

now why didn't it work correctly in this example?

$c = mysql_connect("localhost", "user", "pass");
mysql_select_db("database", $c);
// change our character set
mysql_query("SET CHARACTER SET 'gbk'", $c);
// create demo table
mysql_query("CREATE TABLE users (
    username VARCHAR(32) PRIMARY KEY,
    password VARCHAR(32)
) CHARACTER SET 'GBK'", $c);
mysql_query("INSERT INTO users VALUES('foo','bar'), ('baz','test')", $c);
// now the exploit code
$_POST['username'] = chr(0xbf) . chr(0x27) . ' OR username = username /*'; 
$_POST['password'] = 'anything'; 
// Proper escaping, we should be safe, right?
$user = mysql_real_escape_string($_POST['username'], $c);
$passwd = mysql_real_escape_string($_POST['password'], $c);
$sql = "SELECT * FROM  users WHERE  username = '{$user}' AND password = '{$passwd}'";
$res = mysql_query($sql, $c);
echo mysql_num_rows($res); // will print 2, indicating that we were able to fetch all records

we changed character-set by mysql_query("SET CHARACTER SET 'gbk'", $c) before calling mysql_real_escape_string, so why didn't this function know new character-set?

Was it helpful?

Solution

SET CHARACTER SET / SET NAMES is not enough to protect against the GBK exploit, depending on what version of MySQL you are using.

If you can, use mysql_set_charset / mysqli_set_charset or real prepared statements.

You'll also want to use MySQl 5.0.77 or better. See this earlier post of mine for more information. If you are using older versions of MySQL, you can be vulnerable without the _set_charset functions.

Using prepared statements bypasses this problem entirely.

OTHER TIPS

You are reading the wrong documentation.

You are talking about mysql_real_escape_string , but you are referring to documentation of mysqli_real_escape_string. Note the additional i.

The documentation for mysqli_real_escape_string says:

mysqli::real_escape_string -- mysqli_real_escape_string — Escapes special characters in a string for use in an SQL statement, taking into account the current charset of the connection

Whereas, the documentation for mysql_real_escape_string (which is used in the example):

mysql_real_escape_string — Escapes special characters in a string for use in an SQL statement

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top