针对SQL注入的白名单有效性

时间:2016-02-09 16:34:02

标签: php sql regex pdo sql-injection

假设我有以下内容:

function return_some_info($db, $id){

    if (! preg_match("/^\d{5}$/",$id)) {
      header("Location: safepage.php");
      exit;
    }

    $query="SELECT `column1`, `columns2` FROM `table` WHERE `columnId`=:id ORDER BY `column1` ASC";
    $query_params = array(
        ':id' => $id
    );

    $stmt = $db->prepare($query);
    $stmt->execute($query_params);
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $infoArr[]=$row;
    };
    return $infoArr;
}

让我们说$ id是一个动态变量,可以被恶意用户改变(通常是系统生成的,但可能是被破坏的)。如果$ id应该始终是一个五位整数,使用正则表达式和重定向,是否有任何可能的方式注入只能通过“whiltelisting”只能获得一个五位数整数。因此,例如,如果不使用带参数化查询的PDO,则有:

$query="SELECT `column1`, `columns2` FROM `table` WHERE `columnId`=".$id." ORDER BY `column1` ASC";

对于SQL注入的可能性会有什么不同,因为重定向不会让任何不是五位数的整数过去吗?我不这样做,建议这个或考虑这个(上面的查询没有参数化查询)。我不需要一堆答案来讨论PDO的重要性或类似的东西来停止SQL注入。我试图更深入地理解安全逻辑。所以这个问题并不是关于SQL注入,而是关于以上述方式进行白名单/清理的有效性。

我的整体问题是:无论如何,有人在$ id变量中注入额外的代码会超过正则表达式重定向而不是五位整数吗?

进一步澄清:显然,尽管我努力尝试,但我没有解释我想要的东西。让我复制一些上面的文字:

“我不这样做,建议这样或考虑这个(上面的查询没有参数化查询)。我不需要一堆答案谈论PDO的重要性或类似的东西来停止SQL注入。我我试图更深入地理解安全逻辑。“

我真的在寻找我列出的白名单/敏感正则表达式的有效性。我对此的好奇完全超出了SQL查询,但我想这可能是一个很好的例子。显然不是。 Wiktor实际上回答了我的问题。大多数人都对SQL注入做了大量工作(由你的常识大肆宣传 - 关于这个主题的自封星系专家)。对我真实问题的任何其他回复都将不胜感激。

问候,

2 个答案:

答案 0 :(得分:1)

嗯,这个问题很模糊,很难说出你的实际问题。但至少我可以回答其中一个问题:

  

所以这个问题是......关于以上述方式进行白名单/消毒的有效性。

显然无效,因为每个特定变量都需要特别注意。在这里你需要一个整数,你需要一个布尔值,在某个地方你需要一个字符串。并且您需要更改字符串的整数。等等。

为什么要烦恼所有这些事情?为什么不学习如何使用PDO预处理语句呢?使用PDO,您可以以相同的方式处理所有参数 - 只需将它们分别发送到查询:

function return_some_info($db, $id) {

    $query = "SELECT column1, columns2 FROM table WHERE columnId= ? ORDER BY column1";
    $stmt = $db->prepare($query);
    $stmt->execute([$id]);
    return $stmt->fetchAll();
}

看,正确使用它比你的方法花费更少,并以相同的方式处理任何数据。

安全逻辑非常简单:数据库应该为您完成。对于任何其他媒体/目的地都是如此。应避免手动清理,以支持自动格式化。

通过手动格式化/清理,开发人员将对安全负责。我可以向你保证 - 这是the most unreliable link in the chain。正确的格式化必须由数据库驱动程序完成 - 所以PDO会这样做。这就是你应该总是使用绑定的原因。

如果您不能使用绑定,建议使用白名单 - 例如,对于字段名称。

答案 1 :(得分:1)

嗯,是的...... 如果

  1. 您的白名单代码是正确的
  2. 您的白名单代码没有错误
  3. 您确切知道如何在所有可能的情况下解析和处理所有可能的值
  4. 你没有忘记任何可能漏过的特殊情况
  5. ...然后可能白名单方法可以是安全的。

    重点是,如果 ifs ,这会很多,并且您将来会更改您的代码,并且您会在未来,你会忘记在某个地方以某种方式验证某些东西,并且 会在一天之内泄露一些未经证实的值...

    准备好的语句API的一大优势是你无法破解它。使用值占位符并单独传递值,并使用本机预处理语句API一直执行此操作>无法打破无论你在写这段代码时有多么紧张或醉酒,健忘或愚蠢。

    是的,它在物理上可以以其他方式保护数据库查询,但它人性更难,因此不值得打扰。