为什么 mysql_real_escape_string() 不应避免任何 SQL 注入?
我听人们说过(与 C#/SQL Server 相关,而且与 PHP/MySql 相关):不要手动转义字符串 - 使用存储过程。
好吧,我可以接受这个建议,但是为什么呢?许多人说(包括SO)mysql_real_escape_string()
已经足够了,mysql_real_escape_string()
很好,mysql_real_escape_string()
是第一种保护方式。
为什么?是否存在 mysql_real_escape_string()
失败的情况?至少一个...我不需要很多:)
I've heard people say (in relation to C#/SQL Server, but also in relation to PHP/MySql): Don't escape strings manually - use stored procedures instead.
Ok, I can accept this suggestion, but why? Many say (including on SO) mysql_real_escape_string()
is quite enough, mysql_real_escape_string()
is good, mysql_real_escape_string()
is the first way of protection.
Why? Is there a case where mysql_real_escape_string()
can fail? At least one... I don't need many :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
当mysql_real_escape_string FAIL时:
如果
$_GET['user_id']
设置为1 OR 1=1,则没有特殊字符,也不是过滤。结果:返回所有行。
情况变得更糟。怎么样...如果
$_GET['user_id']
设置为 1 OR is_admin = 1 会怎样?该函数仅设计为在单引号内使用。
When mysql_real_escape_string FAIL:
If
$_GET['user_id']
is set to 1 OR 1=1, there are no special chars and it's not filtered.The result: All rows are returned.
It gets worse. How about this... what if
$_GET['user_id']
is set to 1 OR is_admin = 1?The function is only designed to be used when inside single quotes.
mysql_real_escape_string
可能会出现两个问题:SET NAMES
设置这些编码, 而不是mysql_set_charset
是正确的,它可以仍然让您容易受到攻击更新:
SET NAMES
!)There are two things that can go wrong with
mysql_real_escape_string
:SET NAMES
instead ofmysql_set_charset
as is proper, it can still leave you vulnerableUpdate:
SET NAMES
!)仅供参考:
mysql_real_escape_string()
不会转义%
和_
。如果与 LIKE、GRANT 或 REVOKE 结合使用,这些在 MySQL 中就是通配符。Just for info:
mysql_real_escape_string()
does not escape%
and_
. These are wildcards in MySQL if combined withLIKE, GRANT, or REVOKE
.mysql_real_escape_string()
可能无法清理输入。由于
mysql_real_esacpe_string()
在清理字符串时会考虑字符集。问题来了。您可以通过
mysql_query
函数发送查询来更改连接的字符集。但是,mysql_real_escape_string()
不会注意到您正在使用的集合,并且它会错误地转义某些字符。另一件事是不断手动调用它。即使将其包装在函数中也是 PITA,因为它意味着您必须创建自己的某种数据库包装器/数据库抽象层,以便能够自动调用
mysql_real_escape_string()
。这就是为什么我们在 PHP 中使用 PDO,它可以帮助我们缓解上述所有问题,并且您可以使用参数化准备好的语句,这是处理更改数据的重复查询的更好方法。
准备语句,绑定输入变量,它将根据正在使用的数据库驱动程序和连接的字符集清理输入。它的代码更少并且完全安全。
mysql_real_escape_string()
can fail to clean the input.Since
mysql_real_esacpe_string()
takes character set into account while cleaning strings.There's the problem. You can change character via
mysql_query
function sending the query to change connection's character set. However,mysql_real_escape_string()
is oblivious to the set you're using and it will escape some characters improperly.The other thing is constantly invoking it manually. Even wrapping it in a function is a P.I.T.A. because it implies you have to create some sort of database wrapper / database abstraction layer of your own in order to be able to automate calls to
mysql_real_escape_string()
.That's why we have PDO in PHP which helps us alleviate all of the above and you get to use parametrized prepared statements which are preferable way of dealing with repeating queries that alter the data.
Prepare the statement, bind input variables and it will clean the input according to the database driver being used and connection's character set. It's less code and completely safe.
关于 mysql_real_escape_string() 和 SQL 注入只有一件事 -
前者与后者没有丝毫关系。
虽然这听起来很矛盾,但没有什么比这更真实的了。
这里有 2 个语句证明了这一点
因此,在适用时,无论如何都必须使用此功能,无论有什么危险或恐惧。在任何其他情况下,它都无济于事。
我唯一要补充的是,准备好的语句也不能提供全面的保护。以下是解释和建议:https://stackoverflow.com/a/8255054/285587
There is only one thing about mysql_real_escape_string() and SQL Injection -
The former does not have a slightest relation to the latter.
Although it sounds paradoxical, nothing can be more true.
Here are 2 statements proving it
Thus, when applicable, this function have to be used anyway, despite of whatever dangers or fears. And in any other case it will help nothing.
The only thing I have to add is that prepared statements do not provide full protection either. Here is the explanation and recommendations: https://stackoverflow.com/a/8255054/285587