使用MySQL准备语句仍然能够进行注入

问题描述 投票:0回答:1

我有一个表单将数据插入MySQL。

我正在运行准备好的语句来做到这一点,但不知怎的,我仍然可以做注射。我是MySQL的新手,所以我可能会遗漏一些东西。

<?php

include_once 'db.php';

      $first = mysqli_real_escape_string($conn, $_POST['name']);
      $last = mysqli_real_escape_string($conn, $_POST['lastname']);
      $phone = mysqli_real_escape_string($conn, $_POST['phone']);
      $email = mysqli_real_escape_string($conn, $_POST['email']);
      $nif = mysqli_real_escape_string($conn, $_POST['nif']);
      $address = mysqli_real_escape_string($conn, $_POST['address']);
      $postal = mysqli_real_escape_string($conn, $_POST['postal']);
      $distrito = mysqli_real_escape_string($conn, $_POST['distrito']);

      $sql = "INSERT INTO clients (name, surname, phone, mail, nif_id, address, postal, distrito) VALUES (?, ?, ?, ?, ?, ?, ?, ?);";
      $stmt = mysqli_stmt_init($conn);
      if (!mysqli_stmt_prepare($stmt, $sql)) {
        echo "SQL error";
      } else {
        mysqli_stmt_bind_param($stmt, "ssssisss", $first, $last, $phone, $email, $nif, $address, $postal, $distrito);
        mysqli_stmt_execute($stmt);
      }

编辑

当通过它的URL name=TEST&lastname=TEST&email=TEST&phone=9999999999&nif=&address=&postal=&distrito=Lisboa在上面的文件上运行https://.../includes/addclient.php时会发生这种情况

我错过了什么吗?

mysql prepared-statement sql-injection
1个回答
1
投票

将所有评论结合在一起......

SQL Injection是指某人恶意制造一个增加SQL语句的值。在使用字符串连接构建SQL查询时,这只是一个问题。例如...

$first = $_POST['name'];
$last = $_POST['lastname'];
$sql = "INSERT INTO clients (name, surname) VALUES ('$first', '$last')";

如果有人声称他们的名字是Foo,他们的姓氏是'); delete from clients; select('你有问题。

INSERT INTO clients values ('Foo', ''); delete from clients; select('');

有两种方法可以防止这种情况发生。首先是逃避任何可能是SQL元字符的内容,如引号和分号。这就是mysqli_real_escape_string试图做的事情。

  $first = mysqli_real_escape_string($conn, $_POST['name']);
  $last = mysqli_real_escape_string($conn, $_POST['lastname']);
  $sql = "INSERT INTO clients (name, surname) VALUES ('$first', '$last')";

现在,当他们通过'); delete from clients; select('时,它可能会逃脱到\'\)\; delete from clients\; select\(\'中性化,所以它不能跳出它的报价。这不是100%有效,并且使得难以审核代码以确保您已经考虑了所有可能的注入向量。

更好的方法是使用绑定参数。因为你不再将字符串连接在一起,所以它完全避免了这个问题。每个参数都作为值显式传递给数据库。这意味着直接传递表单参数是安全的。首先转义它们可能会使用额外的反斜杠来破坏这些值。

mysqli_stmt_bind_param($stmt, "ss", $_POST['name'], $_POST['lastname']);
mysqli_stmt_execute($stmt);

除了不需要转义每个值之外,它还使代码更容易审计SQL注入。任何使用字符串连接构建查询的东西都是可疑的,并且有自动化工具可以警告您这一点。

© www.soinside.com 2019 - 2024. All rights reserved.