我有一个表单将数据插入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
时会发生这种情况
我错过了什么吗?
将所有评论结合在一起......
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注入。任何使用字符串连接构建查询的东西都是可疑的,并且有自动化工具可以警告您这一点。