是否从sql注入保护此查询?

时间:2019-07-09 16:45:02

标签: php mysql sql sql-injection

我想知道此sql查询是否已从sql-injection保护起来,是否还可以,或者我应该修改某些内容。

我试图绑定GET中的ID,如果一切正常,我将使用具有该ID的实际查询。

if(isset($_GET['id']) && $_GET['id'] != null) {
  $id = $_GET['id'];

  $stmt = $mysqli->prepare('SELECT id FROM maps WHERE id = ?');
  $stmt->bind_param('i', $id);

  $stmt->execute();

  $result = $stmt->get_result();

  if (mysqli_num_rows($result) == 1)    {
    $row = $result->fetch_assoc();
      $secid = $row["id"];
  } else {
      header("LOCATION: index.php");
  }

  $sql = "SELECT 
  maps.id,
  maps.name,
  maps.description,
  maps.date,
  maps.mcversion,
  maps.mapid,
  maps.category,
  maps.format,
  maps.userid,
  users.username,
  users.rank,
  users.verified,
  users.mc_username,
  (SELECT COUNT(*) FROM likes WHERE likes.mapid = maps.id) AS likes,
  (SELECT COUNT(*) FROM downloads WHERE downloads.mapid = maps.id) AS downloads,
  (SELECT COUNT(*) FROM subscribe WHERE subscribe.channelid = maps.userid) AS subscribes,
  (SELECT COUNT(*) FROM views WHERE views.mapid = maps.id) AS views
  FROM maps
  INNER JOIN users 
      ON maps.userid = users.id
  WHERE maps.id = '$secid'";

  $result = mysqli_query($con,$sql);

  if (mysqli_num_rows($result) > 0) {
      $row = mysqli_fetch_assoc($result);
  } else {
      header("LOCATION: index.php");
  }

} else {
    header("LOCATION: index.php");
}

2 个答案:

答案 0 :(得分:5)

一般经验法则:如果您的查询具有变量插值,例如与$secid一样,则可能没有

使用带占位符值的准备好的语句来确保您没有注入问题。您需要手动进行其他任何检查和验证。 仔细彻底

由于$secid来自数据库,所以不能保证它是什么。那可能是一个VARCHAR列,或者如果不是现在,它可能会在将来。。这就是使SQL注入成为永久威胁的原因。今天有充分根据的假设可能会在以后证明是危险的。

在这种特殊情况下,没有理由不使用占位符值。第一个查询的用途可疑。第二个罐头应该并且应该使用完全相同的方法来显示?而不是一个值。

  

作为强制自己编写安全代码的一种方式,在定义查询时仅使用单引号的字符串。这样,任何意外的SQL注入都将变得无害,相反,您将在数据库中显示文字$值,而不是用户数据,这些值在测试中非常容易发现。除非您要查找SQL注入错误,否则它们不会。

答案 1 :(得分:0)

这是更好的解决方案吧?

if(isset($_GET['id']) && $_GET['id'] != null) {
  $id = $_GET['id'];

  $stmt = $mysqli->prepare("SELECT 
  maps.id,
  maps.name,
  maps.description,
  maps.date,
  maps.mcversion,
  maps.mapid,
  maps.category,
  maps.format,
  maps.userid,
  users.username,
  users.rank,
  users.verified,
  users.mc_username,
  (SELECT COUNT(*) FROM likes WHERE likes.mapid = maps.id) AS likes,
  (SELECT COUNT(*) FROM downloads WHERE downloads.mapid = maps.id) AS downloads,
  (SELECT COUNT(*) FROM subscribe WHERE subscribe.channelid = maps.userid) AS subscribes,
  (SELECT COUNT(*) FROM views WHERE views.mapid = maps.id) AS views
  FROM maps
  INNER JOIN users 
  ON maps.userid = users.id
  WHERE maps.id = ?");

  $stmt->bind_param('i', $id);

  $stmt->execute();

  $result = $stmt->get_result();

  if (mysqli_num_rows($result) == 1)    {
    $row = $result->fetch_assoc();
  } else {
      header("LOCATION: index.php");
      die();
  }

} else {
    header("LOCATION: index.php");
    die();
}