使用十六进制编码来阻止SQL注入是否有任何缺点?

时间:2015-06-29 04:36:49

标签: php mysql sql-injection

在SO上阅读一些SQL注入问题和答案,我看到this answer表明您可以将不受信任的用户输入转换为十六进制,这本质上不需要转义任何类型,因而完全彻底避免了SQL注入的可能性

您使用的数据库抽象层(PDO,mysqli,mysql,Pear DB等)无关紧要

正常工作查询的示例:

$DBH = new PDO('mysql:host=127.0.0.1;dbname=test', 'test', 'testpassword');

// could have been:
//$bookTitle = bin2hex($_GET['title']);
$bookTitle = bin2hex('Catch-22');

$query = "SELECT * from `books` WHERE `title` = UNHEX('$bookTitle')";

foreach ($DBH->query($query) as $row) {
    echo "\n<br />\n";
    print_r($row);
    echo "\n<br />\n";
}

如果你有一个包含如下表格的数据库,我已经在这里提供了足够的代码供你快速运行测试:

CREATE TABLE `books` (`id` INT, `title` VARCHAR(100), `author` VARCHAR(100)) ENGINE=InnoDB CHARACTER SET='utf8';
INSERT INTO `books` VALUES(1, 'Catch-22', 'Joseph Heller');

当然这过于简单 - 您通常会进行输入验证,输出清理以及许多其他抽象,但我们希望专注于这个问题 - 不再需要帮助提供易于执行的示例。

我想知道的是这项技术是否有任何技术弱点。我特别询问这种技术是否具有人类弱点(作为一个草率的程序员更容易做到,因为它显然不如使用参数化查询那么干净。)

是的,我们都同意参数化查询不易受到错误的编程或不幸的疏忽的影响。所以请坚持这个问题 - 这种技术是否有助于无条件地避免各种SQL注入?

有人可以展示一个破坏这种技术的用户输入示例吗?即使是一个极端情况,一些特定的MySQL服务器设置或破坏它的旧PHP版本?

它适用于整数替换:

// could have been:
//$bookID = bin2hex($_GET['id']);
$bookID = bin2hex(1);

$query = "SELECT * from `books` WHERE `id` = UNHEX('$bookID')";

其他想法:

  • 使用这种技术可以避免两次往返数据库,如果使用(非模拟的)预处理语句(尽管是预处理语句!=参数化查询),就会发生这种情况。

  • 其他一些建议技巧的注意事项开始让人们对thisthis等极端情况例外情况进行反复思考。十六进制编码技术是否避免了攻击者使用字符集编码技巧和其他任何东西造成破坏的可能性?

  • 似乎数据库端的解码可能仅限于MySQL / MariaDB,尽管可能有third-party solutions for adding UNHEX() to PostgreSQL(或者 - 不确定 - 在某些数据库中,您可能可以使用其他方法在不使用任何UNHEX函数的情况下将十六进制文字放在查询中

2 个答案:

答案 0 :(得分:1)

我们在已经存在了几年的电子商务系统上使用这种十六进制编码技术。

我还遇到了一个缺点,一旦你为数据库中的每个表编写了一个对象(带有相应的检索和存储功能),它就会从UI中隐藏起来开发人员,他们甚至都没有注意到。

这一项技术适用于

  1. 阻止SQL注入
  2. 支持任何客户端的字符编码
  3. 存储二进制数据
  4. 它也非常快(我们考虑过base64编码,它会产生更短的SQL字符串,但需要更多的CPU)。在测试中,我们发现十六进制编码所有字符串输入之间没有可衡量的性能差异。

      

    这种技术是否有助于无条件地避免各种SQL注入?

    我还没有看到如果这个技术总是使用(当将任何外部数据绑定到SQL语句中时)SQLi怎么可能 -

    正如所有技术(DCoder)所共有的 - 它必须普遍用于提供通用保护 - mysql_real_escape_string也会受到影响。

    用户&#34; N.B&#34;咆哮,但没有提供任何技术论据(可能是他在谈论PokemonGo与CSGO,谁知道?),唯一的答案明显误解了这项技术。

    然而,我确实发现缺乏使用/记录这种技术的人非常惊讶 - 这是我对它有任何疑问的唯一原因。

    它如此简单,简单,全面,并提供了一系列其他有用的好处,很难让我理解为什么每个人都没有做到这一点而且SQLi是一个过去???

答案 1 :(得分:-3)

似乎是合乎逻辑的,因为所有数据,甚至是可能导致注入的用户输入,都将被转换。我一直试图找到绕过它的方法,但我不能。到目前为止,我看到的最大缺点是:1)从数据库视图中,您将无法理解用户的输入。您将从数据库中提取所有内容并将其转换为仅查看或操纵它。 2)无论您提供什么输入,转换后字符串长度都会加倍。