消除危险字符是否可以避免sql注入?


Does eliminating dangerous characters avoid SQL-injection?

避免SQL注入有很多方法如何防止PHP中的SQL注入?

问题是,怎么可能通过removeBadCharacters进行sql-inject呢?

function removeBadCharacters($s)
{
   return str_replace(array('&','<','>','/','''','"',"'",'?','+'), '', $s);
}

它试图抛出危险字符(应用程序不需要这些字符):

$x = removeBadCharacters($_POST['data']);
mysql_query("insert into table (x) values ('".$x."');");
// or
mysql_query("select * from into where name = '".$x."';"); 

为了能够从字符串文本的上下文中注入任意SQL,需要保留该字符串文本。这只能通过引入字符串结束分隔符来实现,在这种情况下是单个',或者通过将字符串字元扩展到前面的',例如,通过使用转义字符':

$a = '''';
$b = ' OR 1=1 OR ';
$c = ' --';
$query = "SELECT * FROM t1 WHERE a='$a' AND b='$b' AND c='$c'";
// result:
// SELECT * FROM t1 WHERE a=''' AND b=' OR 1=1 OR ' AND c=' --'
//                          '_________/           '_______/

现在,当您的函数删除任何''时,似乎不可能离开或扩展字符串文字,因此不可能注入任意SQL。

然而,由于你的函数没有考虑实际的字符编码,如果MySQL的字符编码是GBK,就有可能利用这一点,类似于使用addslashes而不是mysql_real_escape_string时的利用方式:

$a = "'xbf";
$b = " OR 1=1 OR ";
$c = " --";
$query = "SELECT * FROM t1 WHERE a='$a' AND b='$b' AND c='$c'";
// result:
// SELECT * FROM t1 WHERE a='縗 AND b=' OR 1=1 OR ' AND c=' --'
//                          '_________/           '_______/

所以为了安全起见,请使用mysql_real_escape_string或其他经过验证的方法来防止SQL注入。

删除任何字符的想法是完全错误的。

这就是你的方法本质上错误的地方。

你必须正确格式化你的SQL文字而不是破坏它们。

想象一下这个网站使用了这样的"保护":你就不能发表你的问题了!

从字面上回答你的问题-是的,在某些情况下很容易注射。仅仅因为,一次性处理的想法就被打破了。 PHP曾经有一个类似的特性,叫做"魔引号"。这是一个艰难的教训,但现在它终于从语言中删除了。因为我告诉过你的原因:

  • 不生成"data"secure"
  • 它反而破坏了你的数据

是的,这可以通过使用Unicode字符和操作字符集来解决。

你的函数不能处理不同的编码

不要试图自己想出卫生方法,使用已经做好的东西。在mysql_*的情况下,它将是mysql_real_escape_string,然而,你不应该再使用mysql_*,使用PDO或mysqli代替。

参见:如何在PHP中防止SQL注入?