连接动态PDO查询安全,无需bindparam注入

时间:2015-01-09 18:20:11

标签: php mysql security pdo

我有一个页面生成一个记录列表,我希望通过多种可能性来过滤或缩小这些记录。因此,我正在考虑向SQL查询添加可能的“AND”语句。除了传递给查询的LIMIT部分的分页之外,用户生成的数据不会进入查询。

我的问题:

  1. 在LIMIT之后注释是否开放,因为我没有使用bindParam?

    $start_record = $_GET['page'];
    $ids = array('pid_b', 'pid_l', 'pid_g' );
    $qMarks = str_repeat('?,', count($ids) - 1) . '?';
    
    // THIS MY CONDITION FOR TESTING PURPOSES ONLY
    $testVar = 1;
    
    // NOW WE BUILD THE QUERY
    $sqlQuery = "SELECT * FROM inventory_tbl ";
    $sqlQuery .= "WHERE `consignor_record_id` IN ($qMarks) ';
    $sqlQuery .= ($testVar == 1 ? " AND `inventory_status` <> 'active' " : "");
    $sqlQuery .= "ORDER BY `created_date` DESC LIMIT $start_record, 50 ;";
    
    $productSearch = $dbh->prepare( $sqlQuery );
    

3 个答案:

答案 0 :(得分:2)

然后是的,它是开放的SQL注入。一个主要的SQL注入问题是通过union加入多个查询。如果我知道inventory_tbl有多少列以及其他类似于users表的名称,我可以发送页面获取值0 UNION ALL SELECT col1,col2 FROM USERS --,它实际上会从库存表中选择零行并从中选择所有行用户表或类似。或者,如果这不起作用,请发送执行其他代码的限制的子查询。或者甚至是分号来结束select和除了first之外还要执行的任何其他查询。

答案 1 :(得分:1)

来自PDO Wiki

  

在仿真模式下(默认情况下处于启用状态),PDO替代   占位符与实际数据。和&#34;懒惰&#34;绑定(使用数组)   execute()),PDO将每个参数视为字符串。结果,   准备LIMIT?,?查询变为极限&#39; 10&#39;,&#39; 10&#39;这是无效的   导致查询失败的语法。

     

解决方案是关闭模拟(因为MySQL可以排序所有   占位符正确)。

$start_record =  1;//$_GET['page'];
$ids = array('pid_b', 'pid_l', 'pid_g' );
// THIS MY CONDITION FOR TESTING PURPOSES ONLY
$testVar = 1;
//Set up parameters for lazy binding
$params =$ids;//Fill array with ids
array_push($params,$testVar);
array_push($params,$start_record);
$qMarks = str_repeat('?,', count($ids) - 1) . '?';
// NOW WE BUILD THE QUERY
$sqlQuery = "SELECT * FROM inventory_tbl ";
$sqlQuery .= "WHERE `consignor_record_id` IN ($qMarks) ";
$sqlQuery .= "AND $testVar == ? AND `inventory_status` <> 'active' " ;
$sqlQuery .= "ORDER BY `created_date` DESC LIMIT ?, 50 ;";
//To turn emulation off, one can run this code (or set in a connection options array):
$conn->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
$productSearch = $dbh->prepare($sqlQuery );
$productSearch->execute($params);
//Remove echos after testing
echo $sqlQuery;
echo "<br>";
var_dump($params);

<强>结果

SELECT * FROM inventory_tbl WHERE `consignor_record_id` IN (?,?,?) AND 1 == ? AND `inventory_status` <> 'active' ORDER BY `created_date` DESC LIMIT ?, 50 ;

延迟绑定的参数

  array(5) { [0]=> string(5) "pid_b" [1]=> string(5) "pid_l" [2]=> string(5) "pid_g" [3]=> int(1) [4]=> int(1) } 

答案 2 :(得分:0)

此查询不能安全注入。您可以通过$ _GET ['page']注入。