2015-01-09 84 views
0

我有页面生成的记录列表,我想过滤或缩小一些可能性。因此,我正在考虑在SQL查询中添加可能的“AND”语句。除了传递给查询LIMIT部分的分页以外,用户生成的数据不会传递给查询。级联动态PDO查询安全注入无bindparam

我的问题:

  1. ,因为我没有使用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); 
    
+0

它绝对是 – cmorrissey 2015-01-09 18:24:31

+0

我不相信这是除开'LIMIT'如你所说。我很好奇@cmorrissey是怎么想的。 – 2015-01-09 18:25:19

+0

本着教育的精神,你介意解释吗? – SWL 2015-01-09 18:27:22

回答

2

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

+0

谢谢你解释!有没有办法在PDO中阻止它? – SWL 2015-01-09 20:08:00

+1

由于limit接受一个数字,所以你可以检查is_numeric是否为int。 – 2015-01-09 20:16:57

0

该查询是不是从注射安全。您可以通过$ _GET ['page']进行注入。

1

从PDO维基

当在仿真模式(它是在默认情况下),PDO替换占位符 与实际数据。并且使用“惰性”绑定(使用execute()中的数组),PDO将每个参数视为一个字符串。结果, 准备了LIMIT?,?查询变为LIMIT'10','10',这是导致查询失败的无效 语法。

解决方案关闭模拟(因为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 ; 

PARAMS懒惰结合

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