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

时间:2019-03-19 16:41:07

标签: mysql prepared-statement sql-injection

我有一种将数据插入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);
      }

编辑

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

我想念什么吗?

1 个答案:

答案 0 :(得分: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注入。可以用字符串连接构建查询的任何东西都是可疑的,并且有自动化的工具可以警告您。