SQL注入和准备好的语句,何时会出现过度杀伤?

时间:2015-06-01 19:18:58

标签: php mysqli prepared-statement sql-injection

我已经阅读了很多关于sql注入的内容,而且我已经使用了mysqli准备好的声明超过一年了。我越接近我的问题就是这一个Why does this MySQLI prepared statement allow SQL injection?

现在,我想创建一个函数来根据用户的搜索条件运行查询。我使用这个,所以我可以使用很多不同的标准。

这是一个简化的示例,您可以围绕我的问题: 假设我们有两张桌子,一张带轮胎,另一张带轮子。

CREATE TABLE IF NOT EXISTS `wheels` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `brand` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `size` int(11) NOT NULL,
  `price` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `brand` (`brand`),
  KEY `size` (`size`),
  KEY `price` (`price`)
);
CREATE TABLE IF NOT EXISTS `tires` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `brand` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `size` int(11) NOT NULL,
  `price` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `brand` (`brand`),
  KEY `size` (`size`),
  KEY `price` (`price`)
);

现在我们有一个表单让用户进行搜索

<form method='post' ...>
  Looking for : <select name='item'>
    <option value='tires'>Tires</option>
    <option value='wheels'>Wheels</option>
  </select>
  Search by : <select name='type'>
    <option value='size'>Size</option>
    <option value='price'>Maximum price</option>
  </select>
  <input type='text' name='criteria' />
</form>

现在处理请求的php看起来像这样:

$item=filter_input(INPUT_POST,'item',FILTER_SANITIZE_STRING);
$type=filter_input(INPUT_POST,'type',FILTER_SANITIZE_STRING);
$criteria=filter_input(INPUT_POST,'criteria',FILTER_SANITIZE_NUMBER_INT);

function build_query($item,$type,$criteria){
  switch($item){
    case 'tires': $table='tires'; break;
    case 'wheels': $table='wheels'; break;
    defaults: /*error handling : bad search criteria*/ break;
  }
  switch($type){
    case 'size': $field='size'; $operator='='; break;
    case 'price': $field='price'; $operator='<='; break;
    defaults: /*error handling : bad search criteria*/ break;
  }
  $value=intval($criteria);

  $sql= ....

  //Do the rest of sqli magic here and return the results.

}

请注意,只有$条件(变为$ value)才会被硬编码&#39;并从搜索表单发送到DB。 所以问题是:如果$ table,$ field和$ operator变量来自我的php内部代码,是否还需要绑定它们?

换句话说:

这是否过度?

$sql="SELECT * FROM ? WHERE ???"; 
$stmt->bind_param('sssi',$table,$field,$operator,$value);

和/或这是否足够?

$sql="SELECT * FROM ".$table." WHERE ".$field.$operator."?";
$stmt->bind_param('i',$value);

如前所述,这是一个简化的示例,因此您可以更好地理解该问题。

1 个答案:

答案 0 :(得分:1)

是的,您将远程使用PDO。 PDO仅用于参数,而不用于表或运算符。使用您的第二个查询。

http://php.net/manual/en/pdostatement.bindparam.php并不表示允许使用表格和运算符,我记得有一段时间对此进行测试,发现它们不是。

  

将PHP变量绑定到相应的命名或问号   占位符在用于准备的SQL语句中   声明。与PDOStatement :: bindValue()不同,变量绑定为   参考,只会在当时进行评估   调用PDOStatement :: execute()。

     

大多数参数都是输入参数,即参数   以只读方式使用以构建查询。一些司机   支持调用将数据作为输出返回的存储过程   参数,还有一些也作为输入/输出参数发送   数据并更新以接收它。