简体   繁体   English

这个PHP函数是否可以防止SQL注入?

[英]Does this PHP function protect against SQL injection?

I have this function I'm using and I want to be sure that it fully protects against SQL injection attacks: 我有这个我正在使用的功能,我想确保它完全防止SQL注入攻击:

function MakeSafeForQuery($string)
{
    // replace all of the quote
    // chars by their escape sequence

    $ret = str_replace("\\","\\\\",$string);
    $ret = str_replace("'","\\'",$ret);
    $ret = str_replace("\"","\\\"",$ret);

    return $ret;
}

Am I missing anything serious? 我错过了什么严肃的事吗?

Edit: I'm using MySQL by the way. 编辑:我顺便使用MySQL。

In GBK, 0xbf27 is not a valid multi-byte character, but 0xbf5c is. 在GBK中,0xbf27不是有效的多字节字符,而是0xbf5c。 Interpreted as single-byte characters, 0xbf27 is 0xbf ( ¿ ) followed by 0x27 ( ' ), and 0xbf5c is 0xbf ( ¿ ) followed by 0x5c ( \\ ). 解释为单字节字符,0xbf27为0xbf( ¿ ),后跟0x27( ' ),0xbf5c为0xbf( ¿ ),后跟0x5c( \\ )。

How does this help? 这有什么用? If I want to attempt an SQL injection attack against a MySQL database, having single quotes escaped with a backslash is a bummer. 如果我想针对MySQL数据库尝试SQL注入攻击,使用反斜杠转义单引号是一件好事。 If you're using addslashes() , however, I'm in luck. 但是,如果你正在使用addslashes() ,我很幸运。 All I need to do is inject something like 0xbf27, and addslashes() modifies this to become 0xbf5c27, a valid multi-byte character followed by a single quote. 我需要做的就是注入类似0xbf27的东西,并且addslashes()将其修改为0xbf5c27,这是一个有效的多字节字符,后跟单引号。 In other words, I can successfully inject a single quote despite your escaping. 换句话说,尽管你逃脱了,我仍然可以成功地注入一个单一的报价。 That's because 0xbf5c is interpreted as a single character, not two. 那是因为0xbf5c被解释为单个字符,而不是两个。 Oops, there goes the backslash. 糟糕,有反斜杠。

This type of attack is possible with any character encoding where there is a valid multi-byte character that ends in 0x5c, because addslashes() can be tricked into creating a valid multi-byte character instead of escaping the single quote that follows. 任何字符编码都可以进行这种类型的攻击,其中有一个以0x5c结尾的有效多字节字符,因为addslashes()可以被欺骗创建一个有效的多字节字符而不是转义后面的单引号。 UTF-8 does not fit this description. UTF-8不符合此描述。

To avoid this type of vulnerability, use mysql_real_escape_string() 要避免此类漏洞,请使用mysql_real_escape_string()

http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string

To protect against SQL injections, you should not use a function you are writing yourself. 为了防止SQL注入,您不应该使用自己编写的函数。

Instead, you should use a function that's provided by your database driver. 相反,您应该使用数据库驱动程序提供的函数。

For instance : 例如 :


The right way to escape strings depends on both the database system, and its configuration (which is why escaping functions generally require an active database connection) -- which means your function could/would work in most cases, but not necessarily always. 转义字符串的正确方法取决于数据库系统及其配置 (这就是转义函数通常需要活动数据库连接的原因) - 这意味着您的函数在大多数情况下可以/可以工作,但不一定总是如此。

These days, you should use prepared statements , whose parameters aren't vulnerable to injection, rather than sanitizing functions. 现在,您应该使用预处理语句 ,其参数不易受注入,而不是清理函数。 PDO supports them. PDO支持它们。 Read " Writing MySQL Scripts with PHP and PDO " for more information. 阅读“ 使用PHP和PDO编写MySQL脚本 ”以获取更多信息。

Note that only scalar values can be parameterized with most DB drivers. 请注意,只有标量值可以使用大多数DB驱动程序进行参数化。 Compound values (such as used in the IN ( list ) operator) and other parts of statements cannot usually be parameterized. 复合值(例如在IN ( list )运算符中使用)和语句的其他部分通常不能参数化。 For these, you still need to interpolate values into the statement. 对于这些,您仍需要将值插入到语句中。 It's best not to ever use user input directly for anything other than values. 最好不要将用户输入直接用于除值之外的任何其他内容。

Couldn't you just use mysql_real_escape_string or are you trying to do it without a database connection? 难道你不能只使用mysql_real_escape_string或者你是否试图在没有数据库连接的情况下这样做?

(Which seems to defeat the purpose....) (这似乎打败了目的......)

Definitely NO. 绝对没有。

Not because of some exotic encodings you will never meet in your life, but because of the simple fact that escaping alone helps nothing . 不是因为你在生活中永远不会遇到一些异国情调的编码,而是因为单独逃避无助的简单事实。

Adding slashes is not like some divine intervention that instantly prevents scaring injection. 添加斜线并不像一些神圣的干预,可以立即防止注射疤痕。

In fact, it works only if combined with quotes. 实际上,它只有在与引号结合使用时才有效。 If you quote your escaped data - you may consider yourself safe, even with your home-brewed escaping function (as long as your encoding either single-byte or UTF-8). 如果您引用转义数据 - 您可能认为自己是安全的,即使您使用自制的转义功能(只要您的编码为单字节或UTF-8)。 However, sometimes we don't (or even can't) use quotes around our variables and such a place instantly becomes a security hole. 但是,有时我们不会(甚至不能)在我们的变量周围使用引号,这样的地方会立即变成安全漏洞。

For the further explanations you may refer to my previous answer to the similar question: https://stackoverflow.com/a/8061617/285587 有关进一步说明,您可以参考我之前对类似问题的回答: https//stackoverflow.com/a/8061617/285587

As for the accepted answer, just keep in mind that both mysql_real_escape_string() and PDO prepared statements has exactly the same vulnerability if used by itself, without taking required precautions. 至于接受的答案,请记住,mysql_real_escape_string()和PDO预处理语句如果单独使用则具有完全相同的漏洞,而不采取必要的预防措施。 You have to properly set client encoding to make them work as intended. 您必须正确设置客户端编码,以使它们按预期工作。

So, in fact just use mysql_real_escape_string() will help you no more than your own function. 所以,实际上只需use mysql_real_escape_string()就可以帮助你了解自己的功能。

mysql_set_charset() have to be used with mysql_real_escape_string() and in PDO either emulation mode have to be turned off or encoding should be set in DSN mysql_set_charset()必须与mysql_real_escape_string()一起使用,并且在PDO中必须关闭仿真模式或在DSN中设置编码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM