首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这个MySQLI准备语句允许SQL注入?

问为什么这个MySQLI准备语句允许SQL注入?
EN

Stack Overflow用户
提问于 2013-11-07 21:14:45
回答 2查看 1.6K关注 0票数 6

当我今天教学生如何防止SQL注入时,我有点尴尬。在专业项目中,我使用准备语句/参数化查询作为防止SQL注入的一个层(尽管我从未专业地使用过mySQL )。理论上,我认为当使用准备好的语句时,SQL注入是不可能的。

但后来这个成功了..。

代码语言:javascript
复制
$Search = $_GET['s'];
$stmt = $mysqli->prepare("SELECT * FROM products WHERE id = ?");
$stmt->bind_param("i", $Search);
$stmt->execute();
$Results = $stmt->get_result();

如果传递参数"?s=1或1=1“,则可以获得所有产品的完整列表。我仍然不能在最后插入另一个查询,但是我很困惑为什么这种类型的基本SQL注入在mysql/php中是可能的。我假设参数"1 OR 1=1“将被拒绝,因为它不是数字(显然,我可以运行数字检查.)。

有人能解释一下为什么这样做吗,以及我对php/mysql中准备好的语句有什么不理解?

我学校的电脑有一个开箱即用的Zend WAMP安装。

编辑:这是导致我混淆的字符串值:

代码语言:javascript
复制
$Search = "1 OR 1=1";
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-07 21:29:28

没关系,这里没有任何类型的SQL注入,您没有看到所有产品的列表(至少您提供的代码不能显示它)

不需要强制转换到int,让我们更深入地了解bind_param实际上所做的事情:

它有字符串"i“,意思是一个integer参数。

您正在从$_GET传递值,即string

bind_param尝试将字符串转换为int,因此请检查以下php代码:

代码语言:javascript
复制
echo intval('a', 10); // output 0
echo intval('1a', 10); // output 1
echo intval('12a', 10); // output 12
echo intval('b1', 10); // output 0
echo intval('1 or 1=1', 10); // output 1
echo intval("?s=1 OR 1=1", 10); // output 0

所以,你用id=1输出产品,也许你有其中的一些?

票数 8
EN

Stack Overflow用户

发布于 2013-11-07 21:30:22

我试着复制你的案子,但做不到。

数据库

代码语言:javascript
复制
CREATE TABLE `Document` (
  `DataID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `Description` varchar(50) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`DataID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

INSERT INTO `Document` VALUES (1,'BI8392');
INSERT INTO `Document` VALUES (2,'HE8492');
INSERT INTO `Document` VALUES (3,'HE8493');
INSERT INTO `Document` VALUES (4,'HE8490');

代码

代码语言:javascript
复制
<?php
$host = "localhost";
$passwd = "";
$user = "user";
$bdd = "test";

$conn = mysqli_connect( $host, $user, $passwd, $bdd);
mysqli_set_charset($conn, "utf8");

if (!$conn) {
   printf('Error connecting to mysql. Error code: ', mysqli_connect_error());
   exit;
}

$sql = "SELECT * FROM Document WHERE DataID = ?";
if ($stmt = $conn->prepare($sql)) {

    $param = "2 OR 1=1";
    $stmt->bind_param("i", $param);
    $stmt->execute();
    $results = $stmt->get_result();
    $data = mysqli_fetch_all($results);

    var_dump($data);
}

输出

代码语言:javascript
复制
array(1) {
  [0]=>
  array(2) {
    [0]=>
    int(2)
    [1]=>
    string(6) "HE8492"
  }
}

看来,1=1条件被忽略了。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19846830

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档