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

时间:2010-03-31 05:00:55

标签: php sql-injection

我正在使用此功能,我想确保它完全防止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;
}

我错过了什么严肃的事吗?

编辑:我顺便使用MySQL。

5 个答案:

答案 0 :(得分:10)

  

在GBK中,0xbf27不是有效的多字节字符,而是0xbf5c。解释为单字节字符,0xbf27为0xbf(¿),后跟0x27('),0xbf5c为0xbf(¿),后跟0x5c(\)。

     

这有什么用?如果我想针对MySQL数据库尝试SQL注入攻击,使用反斜杠转义单引号是一件好事。但是,如果您使用addslashes(),我很幸运。我需要做的就是注入像0xbf27这样的东西,addslashes()修改它成为0xbf5c27,一个有效的多字节字符,后跟一个引号。换句话说,尽管你逃脱了,我仍然可以成功地注入一个单一的报价。那是因为0xbf5c被解释为单个字符,而不是两个。哎呀,有反斜杠。

     

这种类型的攻击可以通过任何字符编码实现,其中有一个以0x5c结尾的有效多字节字符,因为addslashes()可以被欺骗以创建有效的多字节字符而不是转义单引号接下来。 UTF-8不符合此描述。

     

要避免此类漏洞,请使用mysql_real_escape_string()

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

答案 1 :(得分:3)

为了防止SQL注入,您不应该使用自己编写的函数。

相反,您应该使用数据库驱动程序提供的函数。

例如:


转义字符串的正确方法取决于数据库系统及其配置 (这就是转义函数通常需要活动数据库连接的原因) - 这意味着你的功能在大多数情况下可以/可以工作,但不一定总是如此。

答案 2 :(得分:3)

现在,您应该使用prepared statements,其参数不易受到注入,而不是清理功能。 PDO支持他们。有关详细信息,请阅读“Writing MySQL Scripts with PHP and PDO”。

请注意,只有标量值可以使用大多数数据库驱动程序进行参数化。通常不能对复合值(例如在IN (list)运算符中使用)和语句的其他部分进行参数化。对于这些,您仍需要将值插入到语句中。最好不要直接将用户输入用于除值之外的任何其他内容。

答案 3 :(得分:1)

难道你不能只使用mysql_real_escape_string或者你是否试图在没有数据库连接的情况下这样做?

(这似乎打败了目的......)

答案 4 :(得分:0)

绝对没有。

不是因为你生活中永远不会遇到一些异国情调的编码,而是因为单独逃避无助于这一简单事实。

添加斜线并不像一些神圣的干预,可以立即防止注射疤痕。

事实上,它仅在与引号结合使用时才有效。如果您引用转义数据 - 您可能认为自己是安全的,即使您使用自制的转义功能(只要您的编码为单字节或UTF-8)。但是,有时我们不会(甚至不能)在变量周围使用引号,这样的地方会立即变成安全漏洞。

有关进一步说明,您可以参考我之前对类似问题的回答:https://stackoverflow.com/a/8061617/285587

至于接受的答案,请记住,mysql_real_escape_string()和PDO预处理语句如果单独使用则具有完全相同的漏洞,而不采取必要的预防措施。您必须正确设置客户端编码才能使其按预期工作。

所以,事实上只有use mysql_real_escape_string()只会帮助你,而不仅仅是你自己的功能。

mysql_set_charset()必须与mysql_real_escape_string()一起使用 在PDO中,必须关闭仿真模式或在DSN中设置编码