【问题标题】:How can I protect against SQL injection attacks using Perl's DBI?如何使用 Perl 的 DBI 防止 SQL 注入攻击?
【发布时间】:2011-01-19 00:51:49
【问题描述】:

在将输入放入 MySQL 数据库之前,我可以在 Perl 中使用一个函数来清理输入吗?我不太了解正则表达式,所以在我制作自己的函数之前,我想知道是否已经制作了一个。

【问题讨论】:

标签: mysql perl input-sanitization


【解决方案1】:

清理数据以插入数据库的正确方法是使用placeholders 将所有变量插入到 SQL 字符串中。换句话说,永远不要这样做:

my $sql = "INSERT INTO foo (bar, baz) VALUES ( $bar, $baz )";

改为使用? 占位符:

my $sql = "INSERT INTO foo (bar, baz) VALUES ( ?, ? )";

然后在执行查询时传递要替换的变量:

my $sth = $dbh->prepare( $sql );
$sth->execute( $bar, $baz );

您可以将这些操作与一些 DBI 便捷方法结合使用;上面也可以写成:

$dbh->do( $sql, undef, $bar, $baz );

请参阅DBI docs 了解更多信息。

【讨论】:

    【解决方案2】:

    “使用占位符”答案的次要(并且公认是迂腐的)附录:严格来说,参数化查询不是“清理”。他们不会以任何方式修改数据以确保其安全。相反,它们通过单独的通道发送查询结构(命令)和数据来防止 SQL 注入。

    我觉得这种区别很重要的原因是因为将清理/引用/转义数据和使用参数化查询视为同一件事意味着它们是可互换的,或者充其量只是引用危险字符的更好方法,所以如果你坚持引用而不是费心找出占位符的东西,这没什么大不了的。

    事实上,它们是完全不同的技术,具有完全不同的可靠性水平。引用可以提供出色的注入保护,但坚定的攻击者总是有可能找到一些极端情况,这些情况会破坏或滑过你的引用算法,并允许他们执行成功的 SQL 注入。另一方面,参数化查询提供了针对 SQL 注入的绝对保护。因为命令和数据是分开发送的,所以没有办法数据库引擎可以被欺骗将数据作为命令执行。

    除非您的语言或数据库引擎不允许您在查询中使用参数,否则永远不要引用/转义/清理用户输入以防止 SQL 注入。 始终如果可以的话,请为此目的使用参数化查询。

    强制性链接:http://bobby-tables.com/ 提供了如何在包括 Perl 在内的多种不同语言中使用参数化查询的示例。

    【讨论】:

    • +1 很好的解释:当人们来寻找mysql_real_escape_string() 时,我们大概知道他们心中有SQL 注入,但最好有一个完整的解释。 (顺便说一句,还有mysql_fake_escape_string() 和 `mysql_not_this_one_either_escape_string() 吗?)
    【解决方案3】:

    非常罕见的情况中,您无法使用占位符,如其他答案中所述。但即使在这种罕见的情况下,您也不应该自己篡改数据,因为它为潜在的错误提供了空间。最好使用 DBI 的 quotequote_identifier 方法。此外,它还可以减少您的代码对特定 RDBMS 的依赖。

    免责声明。以下是一个虚拟示例,并不是为了说明我提到的非常罕见的情况

    $dbh->do('INSERT INTO ' . $dbh->quote_identifier($table) . ' (id, name) VALUES '
        '(NULL, ' . $dbh->quote($name) . ')');
    

    【讨论】:

    • 您如何判断使用占位符“使您的代码......依赖于特定的 RDBMS”?在使用 PostgreSQL、MySQL 和 SQLite 时,我遇到了它们之间的差异,但据我所知,占位符的处理方式相同。是否有任何不支持参数化查询的主要 RDBMS 后端? (即使有,我也希望相应的 DBD 驱动程序能够模拟它们。)
    • 你误会了。占位符总是好的。我比较了使用quotequote_identifier 来防止自己篡改数据,因为各种RDBMS 有不同的引号字符。
    • 啊,好的。是的,我将该声明误读为 ->quote(_identifier)? 优于占位符,而不是滚动你自己的清理正则表达式。
    【解决方案4】:

    如何调用数据库?

    DBI 支持使用 placeholders 的预准备语句。如果您使用每个库提供的“查找”方法,DBIx::ClassRose::DB::Object 都会自动清理值。

    【讨论】:

      【解决方案5】:

      答案:使用 SQL 占位符 (?)。

      为什么:SQL语句的结构和占位符所代表的数据值是完全分开发送到数据库的。所以绝对不可能将数据值解释为 SQL 命令。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-08
        • 2015-04-14
        • 2019-01-09
        • 1970-01-01
        • 2020-02-24
        • 2012-03-19
        • 2012-01-05
        • 1970-01-01
        相关资源
        最近更新 更多