PDO准备 - 绑定值

时间:2018-04-10 15:59:49

标签: php sql pdo

我有一个由教程制作的PDO数据库课程。 当我发送一个插入查询时,它中有一个绑定值的方法,实际上它是:

public function query($sql, $params = array()){

    $this->_error = false;

    if($this->_query = $this->_pdo->prepare($sql)){

        if(count($params)){

            $x = 1;
            foreach($params as $param){

                $this->_query->bindValue($x, $param);
                $x++;

            }

        }

        if($this->_query->execute()){

            $this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
            $this->_count = $this->_query->rowCount();

        } else{

            $this->_error = true;

        }

    }

    return $this;

}

我遇到的问题是,我真的不明白这种绑定是如何工作的,我发送此查询:

DB::instance()->query("INSERT INTO table (column) VALUES (<script>alert('test');</script>)");

这是我的instance()方法:

public static function instance(){

    if(!isset(self::$_instance)){

        self::$_instance = new DB();

    }

    return self::$_instance;

}

现在的问题是,在我进入数据库表中的警报测试之后,然后我获取那条警报像一只非常疯狂的兔子一样跳起来的行:(。

我的问题是:这不是一个非常基本的SQL注入吗?为什么我能够将这样的脚本输入到数据库中?如何在不实际执行该脚本的情况下显示这些值?

谢谢你! :d

1 个答案:

答案 0 :(得分:1)

您的代码中没有SQL注入,因为<script>alert('test');</script>不是SQL。

准备好的语句只有在你正确使用它们时才会阻止SQL注入 - 它是一种可以更容易编写安全代码的工具,而不是检查你正在做什么的神奇子弹。您必须通过$params数组提供所有不受信任的数据,而不是将其替换为查询。所以你应该这样做:

$DB::instance()->query("INSERT INTO table (column) VALUES (?)", ["<script>alert('test');</script>"]);
顺便说一下,没有必要在循环中调用bindValue()。可以为execute()方法提供一个参数数组作为参数,因此您可以这样做:

$this->_query->execute($params);

要防止在HTML网页中显示列时执行Javascript,请使用htmlentities()

echo htmlentities($row['column'], ENT_QUOTES);

这可以防止跨站点脚本(XSS)攻击。