【问题标题】:Securing From SQL Injection With PDO API? [duplicate]使用 PDO API 防止 SQL 注入? [复制]
【发布时间】:2012-11-20 04:30:30
【问题描述】:

可能重复:
Are PDO prepared statements sufficient to prevent SQL injection?

我对推出新 API 的主要关注点是安全性,我已经研究了几天。

我是 PDO 用法的初学者,但知道主要结构。但我不知道如何保护查询免受 SQLInjection 的影响。

我的代码如下:

<?php
    $Start = new Db();
    class Db 
    {
        private $dbh = null;

        public function __construct()
        {
            $this->dbh = new PDO('mysql:host=localhost;dbname=pdo', 'root', 'xxxxx');
        }

        public function PDOFetch($Var)
        {
            $sth = $this->dbh->prepare("$Var");
            $sth->execute();
            $result = $sth->fetchAll();
            return $result; 
        }

        public function PDONumb ($Var)
        {
            $sth = $this->dbh->prepare("$Var");
            $sth->execute();
            $count = $sth->rowCount();
            return $count;
        }

        public function PDODel ($Var)
        {
            $Delete = $this->dbh->exec("$Var");
            return $Delete;
        }

        public function PDOQuery ($Var)
        {
            $Query = $this->dbh->query("$Var");
            return $Query;
        }
    }
?>

我将如何防止 SQL 注入和其他漏洞?

编辑:

例如,传递到 API 的查询是从“index.php”页面完成的。

一行是:

    $Num = $Start->PDONumb("SELECT * FROM news");

但后来,当我用这个掩盖了我的踪迹时。我想更高级地使用它,所以它会传递用户定义的变量(因此是 SQL 注入问题)

但目前,通过的查询是由管理员定义的。

【问题讨论】:

  • 防止sql注入确实是人们使用PDO的要点之一。它确实提供保护。为什么你认为你必须自己做?如果您不犯错误,在某处存储额外的 sql 语句标记以在执行时将它们组合起来,PDO 就足够了。
  • @arkascha 我是使用 api 的新手,我已经习惯了 mysql API,它需要手动输入以使用预定义的函数进行保护。那么你的说法是,PDO 保护它自己免受注射?
  • PDO 不会保护自己,如果您使用“准备好的语句”,它会保护您的查询。您首先准备一个包含占位符的语句。在执行期间将值绑定到这些占位符。这就是所谓的“绑定”。检查下面的 Andy Lesters 答案。
  • 请查看bobby-tables.com/php.html,了解如何使用占位符的示例。此外,您不必使用 PDO 来使用占位符变量。
  • PDO 需要将两件事相互分开:要准备的语句和运行时执行的参数。不要混合这些。如果你通过创建一个包含准备执行的 sql 语句的字符串来混合它,那么 PDO 就无法保护你。您可以包装 PDO,您总是必须采取两个步骤:首先准备一个语句,让 PDO 将参数绑定到它。不要使用字符串函数自己绑定它们。

标签: php pdo sql-injection


【解决方案1】:

如果不查看您传入的 SQL,我们无法判断。如果您使用不受信任的数据创建不安全的 SQL 语句,那么它们是否在 PDO 中执行都没有关系。您仍然可以接受 SQL 注入。

例如,如果您从网络获取$userid 并构建:

$sql = "SELECT * FROM users WHERE userid=$userid";

该 SQL 语句对 SQL 注入开放,因为如果 $userid 的值为 0; DROP TABLE users;,那么您将创建的 SQL 将是

SELECT * FROM users WHERE userid=0; DROP TABLE users;

不管你是否通过 PDO 执行它都没有关系:你仍然在执行一个坏人发给你的代码。

要正确使用PDO,需要bind your parameters


与您的问题无关,但新手经常遇到的重要一点:没有必要在单个变量周围加上双引号。你的代码

$Delete = $this->dbh->exec("$Var");

最好写成

$Delete = $this->dbh->exec($Var);

【讨论】:

  • 这绝对是真的。我什至从未想过有人可以以这种方式使用 PDO。值得一提的是!
  • 这就是 OP 的代码正在做的事情。在我看来,它只是从调用者那里获取任意 SQL 代码并执行它。
  • 我基本上是在制作这个以最小化执行 PDO 查询的整个过程,将其减少到仅 1 行并将其传递给定义的函数。查看我对帖子的编辑
  • @DarylGill :您正在尝试抽象抽象层。别。使用准备好的语句,建议的 PDO 方式就足够抽象了。
  • @AndyLester 你是对的,那个包装器确实阻止了 PDO 保护。下次我应该仔细看看。感谢您睁大眼睛。
猜你喜欢
  • 2012-08-04
  • 2014-08-18
  • 2013-02-25
  • 1970-01-01
  • 2011-10-18
  • 1970-01-01
  • 2016-06-08
  • 1970-01-01
相关资源
最近更新 更多