hexing输入是否足以清理SQL查询?

时间:2014-03-21 19:33:29

标签: php mysql sql sql-injection sanitize

昨晚我正在阅读防止SQL注入的内容,我跑过这个答案:

How can I prevent SQL injection in PHP?

“你的常识”中的评论让它听起来像是功能失调/不安全。然而,在我的(尽管有限的)测试中,我发现php的“bin2hex($ var)”适用于我投入的任何内容 - 文字数字,数字字符串,文本字符串 - 即使匹配数字(tinyint)列。 / p>

我的问题是:当通过对其进行清理来清理每个用户输入时,有没有办法注入SQL?从本质上讲,无论何时进行查询,它都会是这样的:

$query="SELECT * FROM table WHERE someidentifier=UNHEX('".bin2hex($unsafe_user_input)."') LIMIT 1"

基本上翻译为:

SELECT * FROM table WHERE someidentifier=UNHEX('0b99f') LIMIT 1

此类安全措施是否存在漏洞?

PS - 我不只是在寻找像“为什么不在准备好的语句中使用PDO或MySQLi”这样的答案?它可能属于抢先优化的巨大罪恶,但我宁愿不加倍我的查询开销(是的,我确实理解它可以更快与多个相同的查询,但这不是我经常遇到的情况)。

4 个答案:

答案 0 :(得分:9)

  

当通过对其进行整理来清理每个用户输入时,有没有办法注入SQL?

如果您知道SQL注入的原因,您可以自己回答这个问题。


我们来看看。 CWE describes SQL injections (CWE-89)如下:

  

该软件使用受外部影响的输入[...]构建全部或部分SQL命令,但它不会中和或错误地中和可能修改预期SQL命令的特殊元素[...]

此外:

  

如果没有在用户可控输入中充分删除或引用SQL语法,生成的SQL查询可能会导致这些输入被解释为SQL而不是普通用户数据。

基本上:生成的SQL查询中受外部影响的输入不会被解释为预期。这里的重要部分是:未被解释为预期

如果用户输入旨在被解释为MySQL string literal,但事实并非如此,那就是SQL注入。但为什么会这样呢?

好吧,string literals有一定的语法,由SQL解析器识别它们:

  

字符串是一个字节或字符序列,包含在单引号(“'”)或双引号(“"”)字符中。

此外:

  

在字符串中,某些序列具有特殊含义[...]。这些序列中的每一个都以反斜杠(“\”)开头,称为转义字符。 MySQL识别Table 9.1, “Special Character Escape Sequences”中显示的转义序列。

此外,为了能够在字符串文字中使用引号:

  

有几种方法可以在字符串中包含引号字符:

     
      
  • 引用“'”的字符串中的“'”可写为“''”。
  •   
  • 引用“"”的字符串中的“"”可写为“""”。
  •   
  • 通过转义字符(“\”)来引用引号字符。
  •   
  • 引用“'”的字符串中的“"”不需要特殊处理,也不需要加倍或转义。同样,引用“"”的字符串中的“'”无需特殊处理。
  •   

由于后面提到的所有序列对于字符串文字都是特殊的,因此必须正确处理任何旨在被解释为字符串文字的数据以符合这些规则。这尤其意味着:如果要在字符串文字中使用任何提到的字符,则必须将它们写为上述方法之一。

因此,如果从这种方式看待它,它甚至不是安全问题,而只是处理数据,以便将它们解释为预期

这同样适用于其他文字以及SQL的其他方面。


那你的问题呢?

  

我的问题是:当通过对其进行清理来清理每个用户输入时,有没有办法注入SQL?从本质上讲,无论何时进行查询,它都会是这样的:

$query="SELECT * FROM table WHERE someidentifier=UNHEX('".bin2hex($unsafe_user_input)."') LIMIT 1"

是的,这样可以安全地进行SQL注入。 bin2hex返回仅包含十六进制字符的字符串。当在MySQL字符串文字中使用它们时,这些字符都不需要特殊处理。

但严重的是,为什么有人会想要使用这些繁琐的格式化技术来提供方便技术(如参数化/预处理语句)的库和框架?

答案 1 :(得分:0)

虽然我不熟悉hexing,但我已成功使用Base64来防止过去从各种脚本中进行mysql注入。

答案 2 :(得分:0)

  

此类安全措施是否存在漏洞?

没有漏洞但也没有优势。传统的字符串格式化同样安全,但没有所有这些无用的hexing / unhexing东西。

因此,使用这些unhex东西膨胀您的查询只是多余的。

从最近的回答来看,最初它是在没有不通知的情况下编写的,因此数字失败,这使得它无法使用。在添加unhex之后,它变得毫无用处和多余。

答案 3 :(得分:0)

$query="SELECT * FROM table WHERE someidentifier=UNHEX('".bin2hex($unsafe_user_input)."') LIMIT 1"

这是一个简单而确定的答案,可以防止使用PHP和MySQL进行SQL注入。

我看过一些评论表明仍然可以使用准备好的或参数化的SQL对SQL注入开放。当这个解决方案很简单且有效时,我认为没有理由大惊小怪。

我已经看过有关CPU时间和内存使用情况的争论,但由于这通常用于在屏幕上键入的用户输入,他们关心RAM使用情况或CPU周期(喘息!)。用户输入500个字符,十六进制版本为一千个字符。除非您的服务器在同一时刻有十万人这样做,否则您不会看到太多差异。

创建清晰,明显,可维护的代码值得花费一些CPU周期和一些RAM。

技术非常简单,很容易记住。随着PHP的不断发展,它也不太可能破坏或发展漏洞。