我正在使用此功能,我想确保它完全防止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。
答案 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中设置编码