mysql PDO和存储过程动态SQL注入

Posted

技术标签:

【中文标题】mysql PDO和存储过程动态SQL注入【英文标题】:mysql PDO and stored procedure dynamic SQL injection 【发布时间】:2017-08-24 09:30:44 【问题描述】:

正如我在许多帖子中看到的,存储过程中的动态 SQL 容易受到 SQL 注入的影响。但是如果我们使用之前的 PDO 和准备好的语句,这仍然不安全吗?

示例:

CREATE PROCEDURE my_sp(
  IN in_var VARCHAR(32)
)
BEGIN
    DECLARE query VARCHAR(255);

    SET @query = CONCAT("SELECT * FROM my_table  WHERE my_column = '",in_var,"' LIMIT 1;";

    PREPARE stmt FROM @query;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END;

$dbh = new PDO( $connection_params );
$dbh->setAttribute(PDO::mysql_ATTR_INIT_COMMAND,"SET NAMES utf8mb4");
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$sql = "CALL my_sp( :in_var )";
$stmt = $dbh->prepare( $sql );
$stmt->execute( array( ':in_var' => $_POST['in_var'] ) );

已编辑:

很抱歉再次提出这个问题,但我还不清楚。

例子:

/* php */
$in_var = " ' OR '1' = '1'; -- ";

/*If I try with PDO without prepared statement and 
without calling a stored procedure THAT WORK ... the injection is succesful*/
$sql = "SELECT * FROM my_table  WHERE my_column = '$in_var' ";

/*With prepared statement NO RESULTS no errors so no injection*/
$sql = "SELECT * FROM my_table  WHERE my_column = :in_var ";

/*Now if I call a Stored Procedure with prepared statement in PDO PHP
but in the procedure I have not used prepared statement that return NO RESULTS no errors so no injection
*/
$sql = "CALL my_sp( :in_var )";

/*If I call the Stored procedure without prepared statement in PDO PHP
that got an PDO error:
Syntax error or access violation: 1064 ...
But seem that injection was not succesful
*/
$sql = "CALL my_sp( '$in_var' )";

我是初学者,我知道我的逻辑可能不太好,但似乎在 PDO 中使用准备好的语句时注入不会发生,尽管它没有在过程中再次使用准备好的语句。

【问题讨论】:

【参考方案1】:

是的,当然。

如果in_var 等于' UNION SELECT password from admins -- 会怎样?

为避免这种情况,您不应使用 cargo cult 准备好的语句,而应使用真实的语句,用占位符替换您的变量。

SET @query = CONCAT("SELECT * FROM my_table  WHERE my_column = ? LIMIT 1;");

PREPARE stmt FROM @query;
EXECUTE stmt USING @in_var;

【讨论】:

以上是关于mysql PDO和存储过程动态SQL注入的主要内容,如果未能解决你的问题,请参考以下文章

事务、存储过程和 PDO

执行Sql语句,包括存储过程,可以动态生成返回实体

我想使用 T-SQL 创建一个存储过程,该过程基于不易受到 SQL 注入攻击的外部数据动态创建一个表

使用 PDO 调用带有 Out 参数的存储过程

PHP MySQL PDO 存储过程和 INOUT 参数

如何在 MySQL 存储过程中使用动态 SQL