当前位置: 首页 > 知识库问答 >
问题:

SQL注入和prepared语句,何时会被过度使用?

孔华池
2023-03-14

我已经读了很多关于sql注入的书,并且已经使用mysqli编写的语句一年多了。我越接近我的问题是,为什么这个MySQLI编写的语句允许SQL注入?

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

这里有一个简化的例子,你可以围绕我的问题来思考:假设我们有两张桌子,一张有轮胎,一张有轮子。

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.

}

请注意,只有$标准(成为$值)不是“硬编码”的,并从搜索表单发送到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个答案

董元徽
2023-03-14

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

http://php.net/manual/en/pdostatement.bindparam.php不表示允许使用表和运算符,我记得不久前测试过,发现它们不允许。

将PHP变量绑定到用于准备语句的SQL语句中相应的命名占位符或问号占位符。与PDOStatement::bindValue()不同,该变量被绑定为引用,仅在调用PDOStatement::execute()时进行计算。

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

 类似资料:
  • 我对where条件、order by和limit有一个查询。我使用准备好的语句来设置where条件和限制。当前,我使用字符串append作为order,从而导致SQL注入漏洞。

  • 问题内容: 今天,当我在教学生如何防止SQL注入时,我有些尴尬。在专业项目中,我已经使用准备好的语句/参数化查询作为防止SQL注入的一层(尽管我从未专业地使用过mySQL)。从理论上讲,我认为使用准备好的语句时不可能进行SQL注入。 但是后来这起作用了… 如果我传递参数“?s = 1 OR 1 = 1”,那么我可以获得所有产品的完整清单。我仍然无法在末尾插入另一个查询,但是我对为什么在mysql

  • 在我的应用程序中,我们从UI收集一些用户输入,并基于这些值生成具有不同“where”条件的动态SQL,以查询数据。发现这段代码有一些SQL注入缺陷。 序列号-可以是一个值、一个值、一个值或两个值。2.创建日期-可以是一个值、一个值、一个值或两个值 ReportTypeNumbers-可以是一个或一个或两个以上 ReportTitleNames-这可以是一个或一个,也可以是两个以上 基于这些输入值,

  • 我试图使用以下JDBC语句将一些值插入到来自Java的Oracle DB中: 序列创建如下: 我得到以下错误, 但当我尝试手动插入到表中时,它是成功的。 有什么问题?

  • 我正在处理的目标系统不支持PDO ist,尽管我在Postgres-DB8.2+上使用PHP 5.1.x寻求防止SQL注入的解决方案。目前没有机会切换到PDO。 我目前的解决方案是pg_prepare-prepared语句: 该函数从查询字符串创建一个名为stmtname的准备好的语句,该语句必须包含单个SQL命令。stmtname可以是“”来创建未命名语句,在这种情况下,任何先前存在的未命名语句

  • 假设上面的代码是我的查询。什么是一个安全的替代方案,将允许自动增加在mySQL数据库。