为什么 mysql_real_escape_string() 不应避免任何 SQL 注入?

发布于 2024-12-22 00:51:50 字数 340 浏览 0 评论 0原文

我听人们说过(与 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

段念尘 2024-12-29 00:51:50

当mysql_real_escape_string FAIL时:

$sql = "SELECT * FROM users WHERE id=" + mysql_real_escape_string($_GET['id']);

如果$_GET['user_id']设置为1 OR 1=1,则没有特殊字符,也不是过滤。

结果:返回所有行。

情况变得更糟。怎么样...如果 $_GET['user_id'] 设置为 1 OR is_admin = 1 会怎样?

该函数仅设计为在单引号内使用。

When mysql_real_escape_string FAIL:

$sql = "SELECT * FROM users WHERE id=" + mysql_real_escape_string($_GET['id']);

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.

半衬遮猫 2024-12-29 00:51:50

mysql_real_escape_string 可能会出现两个问题:

  • 您可能会忘记使用它。
  • 如果您正在使用某些特定的多字节连接编码,并且已使用 SET NAMES 设置这些编码, 而不是 mysql_set_charset 是正确的,它可以仍然让您容易受到攻击

更新:

  • 您使用 UTF-8 是安全的(尽管这并不意味着您应该继续使用SET NAMES!)
  • 解释,请参见此处

There are two things that can go wrong with mysql_real_escape_string:

  • You can forget to use it
  • If you are using some specific multibyte connection encodings, and you have set these encodings with SET NAMES instead of mysql_set_charset as is proper, it can still leave you vulnerable

Update:

  • You are safe with UTF-8 (although this does not mean that you should continue using SET NAMES!)
  • For an explanation, see here
樱花落人离去 2024-12-29 00:51:50

仅供参考:
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 with LIKE, GRANT, or REVOKE.

小红帽 2024-12-29 00:51:50

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.

两人的回忆 2024-12-29 00:51:50

关于 mysql_real_escape_string() 和 SQL 注入只有一件事 -

前者与后者没有丝毫关系。

虽然这听起来很矛盾,但没有什么比这更真实的了。

这里有 2 个语句证明了这一点

  1. ,您只需转义带引号的字符串,因为此函数没有任何帮助。
  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

  1. You have to escape quoted strings only, as this function helps nothing else.
  2. In fact, you have to escape every string you are adding to the query, even safiest one. just because it may contain some special character and thus break the query (just as an accident, not malicious plot).

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文