为什么 mysql_real_escape_string() 不能正常工作?
在 mysql_real_escape_string() 的文档中说:
...,考虑到当前 连接的字符集所以 将其安全地放置在 mysql_query()
现在为什么在这个示例?
$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
我们在调用mysql_real_escape_string
之前通过mysql_query("SET CHARACTER SET 'gbk'", $c)
更改了字符集,那么为什么这个函数不知道新的字符集?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
SET CHARACTER SET
/SET NAMES
不足以防范 GBK 漏洞,具体取决于您使用的 MySQL 版本。如果可以,请使用
mysql_set_charset
< /a> /mysqli_set_charset
或者真正准备好的陈述。您还需要使用 MySQl 5.0.77 或更高版本。 查看此内容我之前的帖子了解更多信息。如果您使用旧版本的 MySQL,如果没有
_set_charset
函数,您可能容易受到攻击。使用准备好的语句可以完全绕过这个问题。
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.
您正在阅读错误的文档。
您正在谈论 mysql_real_escape_string ,但您指的是mysqli_real_escape_string 的文档。请注意附加的i。
mysqli_real_escape_string 的文档说:
而 mysql_real_escape_string 的文档(在示例中使用):
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:
Whereas, the documentation for mysql_real_escape_string (which is used in the example):