4

我在我的一个 php 文件中使用以下代码从数据库中获取数据:

$products = $this->db->get_rows('SELECT * from products WHERE shop_id='.$_SESSION['shop_id'].'AND tags,title,text LIKE \'%'.$_POST['search'].'%\'');

有问题吗?我的意思是可以注入 LIKE 运算符?

已编辑

请提供以这种方式注入的示例

4

4 回答 4

10

任何算子都可以在没有绑定的情况下注入。

$_POST['search'] = "1%'; DROP TABLE myTable LIKE '%";

将使

.... AND tags,title,text LIKE '%1%'; DROP TABLE myTable LIKE '%%'

阅读如何绑定参数

于 2013-03-22T21:13:05.240 回答
2

当然这可以注入,你需要清理你的输入。现在,您正在获取原始发布数据并将其插入到您的 SQL 语句中。

你应该通过某种数据清理来运行你的 POST 数据,比如 mysql_real_escape_string 之类的

或者至少准备好的陈述。让服务器端代码为您完成工作。

于 2013-03-22T21:12:59.703 回答
1

永远不要使用这样的数据库查询,不要用变量构造字符串并将其用于数据库活动。

通过将变量插入到字符串中,构造一个稍后将准备和执行的字符串,使它们不像“命令”而是像“值”。

你可以这样做:

$query = "SELECT * from products WHERE shop_id = :shopId;"; // An example, you can finish the rest on your own.

现在,您可以准备语句(我建议为此使用 PDO)。

 $statement = $db->prepare($query); // Prepare the query.

现在您可以在准备好的查询中执行变量:

$statement->execute(array(
    ':shopId' => $_SESSION['shop_id']
));

如果您要插入或更新,那么您会想要这样做:

$success = $statement->execute(array(
    ':shopId' => $_SESSION['shop_id']
));

它将布尔值存储在 $success 中,或者如果您正在选择,您可以从结果中获取值:

$statement->execute(array(
    ':shopId' => $_SESSION['shop_id']
));
$result = $statement->fetch(PDO::FETCH_ASSOC);
if($result )
{
    // You can access $result['userId'] or other columns;
}

请注意,您实际上应该将其设为一个函数,并将 $shopId 传递给函数,而不是会话本身,并检查会话是否实际存在。

我建议使用谷歌搜索如何使用 PDO,或查看我的一个示例:How to write update query using some {$variable} with example

于 2013-03-22T21:28:42.980 回答
1

这真的很糟糕。将 var 拉入 SQL 语句而不清理或检查它们是获取 pwnd 的好方法。人们可以在代码中注入一些东西。另一种需要注意的注入方法,1=1 总是返回 true。

$products = $this->db->get_rows('SELECT * from products WHERE shop_id='.$_SESSION['shop_id'].'AND tags,title,text LIKE \'%'.$_POST['search'].'%\'');

//This example expects no result from the table initially so we would blind attack the DB to pull the admin record.
$_POST['search'] = "-1\'; union all select * from users limit 1;";

有人调用拉起数据库中的顶级帐户(如管理员)。

$user_id = $this->db->get_rows('SELECT * from users WHERE email="'.$_POST['email'].'" and password="'.$_POST['password'].'"');

//This always returns true so now I'm the admin again
$_POST['password'] = "x\' or 1=1 limit 1";

您还需要小心您在屏幕上打印的内容。

$user_id = $this->db->get_rows('SELECT * from users WHERE email="'.$_POST['email'].'" and password="'.$_POST['password'].'"');

您回显的消息“$_POST['email'] 不存在用户名”可以替换为其他内容。

$_POST['email']=";

$fp = fopen('index.php', 'w');
fwrite($fp, \"header('Location: http://badwebsite.com;');\"; 
fclose($fp);";

index.php 现在可以让人们访问完全不同的网站,其中存在受感染的页面或站点上的受感染页面。

如果您正在检查 ID,请执行以下操作:

if(preg_match('!^[0-9]$!',$_POST['id'])){
    $id = $_POST['id'];
} else {
  //flush
}

或计算可能记录的数量......如果您只期待一个并且您获得了数据库中的所有记录,那么这是一次注入尝试。

 if(is_numeric($_POST['id'])){
    $id = $_POST['id'];
    $count = mysql_result(mysql_query("select count(*) from users where id='$id''),0);
 }
于 2013-03-22T23:19:27.123 回答