有很多关于addslashes和mysql_real_escape函数如何不安全地防止注入的讨论。事实上,即使像 Wordpress 这样的大型框架或 CMS 也在使用这个功能,而且到目前为止它们都做得很好。
我知道使用 GBK 字符集时有一些特定的场景,或者可以使用 utf8_decode 来注入一些 sql 代码,或者一些简单的示例,例如 1' OR 1 --
当有一个简单的情况时可以使用涉及到的地方。
然而,经过一些研究后,如果字符集是 UTF-8,则似乎很难将某些内容注入到使用 addslashes 或 mysql_real_escape 的简单查询中,让我们承认,这是最常见的情况。
因此,鉴于这个新手脚本,请提供一个sql注入POC(记住UTF-8字符集)
$mysql['username'] = addslashes($_POST['username']);
$mysql['password'] = addslashes($_POST['password']);
$sql = "SELECT *
FROM users
WHERE username = '{$mysql['username']}'
AND password = '{$mysql['password']}'";
更新 - 我只需要一个简单的示例,而不是完整公开该过程。即使是来自谷歌的链接也可能有效。
There is a lot of talk about how addslashes and mysql_real_escape function are not safe to prevent injections. The truth is even the big frameworks or CMSs like Wordpress are using this functions and they do a god job so far.
I know there are some particular scenarios when using GBK charset, or utf8_decode can be used to inject some sql code, or some simple examples like 1' OR 1 --
that can be used when there is a simple where involved.
However, after a bit of research it seems very hard to inject something into a simple query with addslashes or mysql_real_escape used if the charset is UTF-8 and let's admit it, this is the most common scenario.
So, given this newbie script, pls provide a sql injection POC ( remember UTF-8 charset )
$mysql['username'] = addslashes($_POST['username']);
$mysql['password'] = addslashes($_POST['password']);
$sql = "SELECT *
FROM users
WHERE username = '{$mysql['username']}'
AND password = '{$mysql['password']}'";
Update - I just need a simple example not a full disclosure of the process. Even a link from google might work.
发布评论
评论(1)
更新2:
经过进一步研究,5.0.77之前的MySQL版本单独与
SET NAMES
结合使用时可能容易受到GBK问题的影响。早些时候人们认为只有 5.0.22 及更早版本容易受到攻击。这意味着,如果您使用 5.2 之前的 PHP 版本(其中引入了 mysql_set_charset/
mysqli_set_charset
),您的代码可能在特定情况下容易受到攻击,精心打造的条件。如果您无法使用 PHP 5.1,请确保您使用的是 MySQL 5.0.77 或更高版本。 5.0.77“仅”发布了两年,但已被推送到 RHEL/CentOS 5.x 的存储库中,RHEL/CentOS 5.x 是更流行的发行版,坚持使用 MySQL 5.0.x 系列和 PHP 5.1.x 系列。
升级吧,人们!
更新1:最近的另一个问题发现了GBK 的来源: MySQL 中的错误修复5.0.22。早于此版本的版本在使用
mysql_real_escape_string
以外的任何内容与mysql_set_charset
而不是只是SET NAMES< /代码>。 mysqli 等效名称为
mysqli_set_charset
。PDO 中似乎没有与
mysql_set_charset
等效的内容。这可能是因为它可以使用 MySQL 本机准备好的语句,这可能不受问题的影响,或者SET NAMES
是否足以让其底层转义机制按预期工作。无论如何,如果您使用
5.0.225.0.77 之前的任何 MySQL 版本,并且没有非常小心地确保您只传递已知字符集的字符串< /strong>,你可能会发现自己很容易受到攻击。我将保留原始帖子的其余部分不变,但我已经更新了 tldr。
这是正确的一半。使用addslashes来防止SQL注入是完全错误的,因为它不能保证为所有数据库提供正确的转义方法,主要是因为它添加了反斜杠,有时转义机制完全不同。
如果您陷入了被称为“mysql”扩展(而不是使用 PDO 或 mysqli)的史前垃圾堆的贫民窟,那么
mysql_real_escape_string
是您在使用时获得的最佳保护之一。需要将一些 SQL 连接在一起。您可能正在考虑创建格式错误的 UTF-8 序列,但是我只将其视为 XSS 机制,绝不是 SQL 注入机制。使用
应该是足够好的保护(通常通过在错误序列处截断字符串,这是一种可接受的故障模式当你受到攻击时 - - 合法请求中不应出现格式错误的序列)。iconv
运行字符串>//IGNORE//TRANSLIT此外,虽然非拉丁语言中有大量的“引号”字符,但 MySQL 相当不错,实际上只遵守标识符的反引号和双引号以及字符串值的单引号。
进一步考虑一下,如果将其视为不同的字符集,则另一个字符集中可能存在一些字符序列,其中可能在中间包含单引号。然而,addslashes 很可能完全不了解字符集,而只对原始字节起作用。它会在序列中间插入一个反斜杠,然后将其炸毁。然而,这应该只会导致有关错误字符集信息的抱怨。
另一方面,mysql_real_escape_string 是根据内置连接字符集的知识而设计的,因此如果它看到的是序列而不是引号,则不会转义序列。但是,因为它会将其识别为序列而不是引用,所以根本没有危险。
最终,如果您认为这是一个问题,您有责任确保仅接受预期字符集的输入,并在不匹配时将所有输入转换为您所需的字符集。这很少会妨碍合法的请求。
tl;dr: 除非您使用的是非常旧的 MySQL 版本和/或不能确保您的数据采用已知良好的字符集,否则不必担心。始终使用特定于数据库的转义机制以获得最大的安全性,并始终假设用户是来抓你的。
Update 2:
After further research, MySQL versions prior to 5.0.77 may be vulnerable to the GBK issue when combined with
SET NAMES
alone. It was earlier believed that only 5.0.22 and earlier were vulnerable.This means that if you are using PHP versions prior to 5.2, in which
mysql_set_charset
/mysqli_set_charset
were introduced, your code may be vulnerable under specific, well-crafted conditions.If you're stuck on PHP 5.1, please ensure that you are using MySQL 5.0.77 or later. 5.0.77 is "only" two years old, but has been pushed into the repositories for RHEL/CentOS 5.x, the more popular distribution stuck with the 5.0.x series of MySQL and 5.1.x series of PHP.
Get upgrading, people!
Update 1: Another recent question has uncovered the source of the GBK thing: A bugfix in MySQL 5.0.22. Versions earlier than this are severely vulnerable when using anything other than
mysql_real_escape_string
combined withmysql_set_charset
instead of justSET NAMES
. The mysqli equivilent is namedmysqli_set_charset
.There does not appear to be an equivilent of
mysql_set_charset
in PDO. This may be either because it can use MySQL native prepared statements, which may be immune from the problem, or whetherSET NAMES
is enough for their underlying escaping mechanism to work as expected.Regardless, if you're using any MySQL version prior to
5.0.225.0.77 and are not taking extreme care to ensure that you're only passing in strings in a known character set, you may find yourself open to attack.I'm leaving the rest of my original post unmodified, but I have updated the tldr.
This is half correct.
addslashes
is entirely the wrong thing to use to protect against SQL injection because it is not guaranteed to provide the right escaping method for all databases, mainly because it adds backslashes and sometimes the escaping mechanism is entirely different.If you're stuck in the ghetto of the prehistoric lump of crap known as the "mysql" extension (instead of using PDO or mysqli),
mysql_real_escape_string
is some of the best protection you've got when you need to concatenate together some SQL.You're probably thinking of creating malformed UTF-8 sequences, however I've only ever seen this as an XSS mechanism, never an SQL injection mechanism. Running strings through
iconv
with//IGNORE//TRANSLIT
should be good enough protection (usually by truncating the string at the point of the bad sequence, which is an acceptable failure mode when you're being attacked -- malformed sequences should never happen in legitimate requests).Further, while there are plenty of "quote" characters in non-Latin languages, MySQL is pretty decent at only actually obeying the backtick and double quote for identifiers and the single quote for string values.
Thinking about it more, perhaps there's some sequence of characters in another character set that might include a single quote in the middle, if taken as a different character set. However, it's very, very likely that
addslashes
is entirely ignorant of character set, and just works on the raw bytes. It'd stick a backslash in the middle of a sequence, and blow it up. However, that should just result in a whine somewhere along the lines about bad character set information.mysql_real_escape_string
, on the other hand, is designed with knowledge of the connection's character set built in, so it wouldn't escape the sequence if it sees the sequence instead of a quote. However, because it would recognize it as a sequence instead of as a quote, there's no danger at all.Ultimately if you think this is a problem, it's your responsibility to ensure that you accept input in only the expected character sets, and transform all input to your desired character set if there's a mismatch. This will rarely if ever trip up a legitimate request.
tl;dr: Not a concern unless you're using a really old MySQL version and/or aren't making sure your data is in a known-good character set. Always use database-specific escape mechanisms for maximum safetey, and always assume the user is out to get you.