【问题标题】:How do we know PDO is escaping SQL Injections?我们如何知道 PDO 正在逃避 SQL 注入?
【发布时间】:2011-06-05 09:17:54
【问题描述】:

我是 PDO 库的新手。我正在使用 mysql 作为我的数据库的开发环境。我可以在使用“?”时使用准备和执行功能来运行我的查询。使用命名占位符时的占位符和 bindParam 方法(例如:“:column”)。

在此之后,我尝试查看 PDO 是否通过添加任何引号来像 mysql_real_escape_string 那样对查询进行任何类型的转义。我正在尝试查看查询的外观,但我得到的只是已传递到 prepare 语句中的语句,而不是将要执行的查询。

我尝试对 $result->execute() 和 $result->fetch() 进行 var_dump,但 execute 语句为我提供了带有占位符的 prepare 语句的 sql,而 fetch 语句为我提供了该查询的结果。

有没有办法查看将要运行的查找查询,或者至少在运行查询之前查看参数的外观??

我希望我的问题很清楚。 :|

【问题讨论】:

  • 你多虑了。准备好的语句以 100% 逃避您的输入。如果您需要查看最终查询的样子,则必须设置数据库查询日志。
  • @netcoder Prepared statements 不会转义任何内容(除非在兼容模式下)。并且查询日志中没有新内容
  • @Col。 Shrapnel:嗯,技术上是的,虽然你可以用你想要的方式来表达它。至于“查询日志中没有新内容”,我根本不明白这是什么意思……
  • @netcoder 不,它没有。从技术上或字面上或其他方面。下面有一个关于准备好的语句如何工作的链接,你会发现它非常有启发性。在您仔细学习并尝试从中运行代码之前,请不要发表评论
  • @Col。弹片:这是一个 PDO 问题,是的,PDO 中的准备好的语句会转义输入。在你学会一些外交之前,请不要发表评论。

标签: php mysql pdo sql-injection prepared-statement


【解决方案1】:

直截了当。

PDO 有两种运行准备好的语句的模式:

  1. 本机模式。查询和数据发送到数据库se-pa-ra-te-ly。这意味着数据永远不会添加到查询中。因此,不能造成任何伤害。曾经。查询按原样发送到数据库,带有 ? 标记(但没有被 PDO 替换为 ?s 的命名占位符)
  2. 兼容模式。 PDO 通过用绑定变量替换占位符来进行旧式查询,这取决于变量名。字符串被引用/转义,其余的被转换为它的类型。

这两种方法都非常安全。

真正的危险始于你有一个变量标识符...

【讨论】:

  • 为什么变量标识符很危险?我认为它更安全,因为我们甚至验证了数据类型?
  • @macha 我的意思是一个字段名。比如SELECT * FROM table ORDER BY $column_name确实很危险
【解决方案2】:

启用一般查询日志,并在您运行简单语句时观察对服务器实际执行的查询 - 执行一些插入操作,例如,使用包含嵌入式引号或 nuls 的字符串。

【讨论】:

    【解决方案3】:

    当你写这样的东西时:

    $stmt = $pdo->prepare('SELECT * FROM tbl_name WHERE col_name = :col_name;');
    $stmt->bindValue('col_name', 'some \' value');
    $stmt->execute();
    

    实际查询是...SELECT * FROM tbl_name WHERE col_name = :col_name;。这称为准备好的语句。首先,您向数据库发送查询,然后发送查询参数。 PDO 不合并查询和参数。

    您可能认为PDOStatement::bindValue() 做了类似的事情:

    public function bindValue($placeholer, $value, $valueType = PDO::PARAM_STR) {
        $this->query = str_replace($placeholder, $this->quote($value, $valueType), $this->query);
    }
    

    但它没有

    它做了更多类似的事情:

    public function execute() {
        try {
            $this->sendQueryToDatabase($this->query);
    
            // Query is valid
            $this->sendParametersToDatabase($this->parameters);
    
            return $this->fetchResultSet();
        } catch (... $e) {
            // Query is invalid (eg. syntax error)
            throw ...;
        }
    }
    

    Read more about Prepared Statements

    【讨论】:

    • 那么我们如何知道发送的参数是否安全?我们需要事先检查吗???
    • 参数不能不安全,因为它们不是查询的一部分。它们只是原始数据。
    • 嘿,我知道这可能有点太高级了,您知道如何解析查询以及如何发送/替换这些参数吗?
    • 查询及其参数是单独发送的,我猜它们永远不会合并(你必须研究 MySQL 源代码才能知道它是如何工作的)。即使某些参数包含' OR do badCode --,它也会被视为原始文本,并且这样的值将被插入到列中。
    • 如果传递了你说的'Or do badcode'--的参数,它会伤害数据库吗?因为不会转义?
    【解决方案4】:

    prepare 语句由 mysql 处理,所以 pdo 不要逃避请求, pdo 发送请求并在参数“之后”

    【讨论】:

    • 不知道你为什么会被否决,这实际上是真的。
    • 这实际上不是真的,PDO 通常模拟预准备语句,因为服务器端预准备语句虽然受支持,但通常不是一个好主意。
    • 服务器端准备好的语句不好;它们通常会导致更差的性能和更低的健壮性,但您可能会发现并非如此。不过没关系,PDO不需要用到它们,仿真是个好东西。
    • 我对这个答案投了反对票,因为尽管我了解准备好的陈述的工作原理,但语言混乱使我无法理解发帖人在说什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-28
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-01
    相关资源
    最近更新 更多