白名单如何使动态查询容易受到SQL注入的攻击?


How can whitelisting leave dynamic queries vulnerable to SQL injection?

有相当多的各种各样的"X是否足以防止SQL注入?"的问题,但我还没有能够找到一个很好地解释这个特定的事情。

因为我不能在准备好的语句中绑定列名的值,必须有一些其他安全的方式来接受用户输入的排序查询和其他类型的事情,准备好的语句将无法帮助。如果我有一个从$_GET中取出的$sort_column,我显然不应该直接在查询中使用它。

$no = "SELECT col1, col2, col3 FROM table ORDER BY $sort_column;";

而不是只是转义$sort_column并试图运行查询,似乎我可以事先检查表的合法列名列表。这样我就可以告诉用户他们选择了一个无效的列,而不需要从数据库错误中找出原因。从我所读到的,即使我这样做,使用$sort_column而不逃避它仍然是不安全的,但我不明白如何,除非in_array不像我认为的那样工作。

$good_columns = array("col1", "col2", "col3");
if (in_array($sort_column, $good_columns, true)) {
    $sql = "SELECT col1, col2, col3 FROM table ORDER BY $sort_column;";

如果我使用我的"安全"数组的列名,而不是使用用户提供的值呢?

function is_column($column, $good_columns) {
    $key = array_search($column, $good_columns);
    if ($key !== false) {
        return $good_columns[$key];
    }
    return false;
}
$good_columns = array('col1', 'col2', 'col3');
$my_column = is_column($sort_column, $good_columns);
if ($my_column) {
    $sql = "SELECT col1, col2 FROM tbl1 ORDER BY $my_column;";

我确实逃避一切,我并不是试图避免去做或者提倡不去做。我很好奇为什么这样的东西仍然是脆弱的

这样做是不安全的,你当然可以这样做。问题在于,您可能习惯于在向项目添加更多代码的过程中先验证变量,然后直接将它们插入到查询中。如果您错过了在代码中的某个地方检查变量,那么您将不容易找到错误或跟踪sql注入的来源。最好习惯在查询中使用每个变量之前转义它。