如果用户输入未经修改就插入到SQL查询中,则应用程序很容易受到SQL注入的攻击,如下例所示:

$unsafe_variable = $_POST['user_input']; 

mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");

这是因为用户可以输入类似值的内容);DROP TABLE表;--,并且查询变为:

INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')

可以采取什么措施防止这种情况发生?


当前回答

我认为如果有人想使用PHP和MySQL或其他数据库服务器:

考虑一下学习PDO(PHP数据对象)——它是一个数据库访问层,提供了访问多个数据库的统一方法。考虑学习MySQLi


库示例:

----个人数字助理

-----没有占位符-SQL注入时机成熟!这很糟糕

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) values ($name, $addr, $city)");

-----未命名占位符

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) values (?, ?, ?);

-----命名占位符

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) value (:name, :addr, :city)");

---MySQLi

$request = $mysqliConnection->prepare('
       SELECT * FROM trainers
       WHERE name = ?
       AND email = ?
       AND last_login > ?');

    $query->bind_param('first_param', 'second_param', $mail, time() - 3600);
    $query->execute();

P.S:

PDO轻松赢得了这场战斗。支持12个不同的数据库驱动程序和命名参数,我们可以习惯它的API。从安全的角度来看,只要开发人员按照应该使用的方式使用它们,它们都是安全的

其他回答

从安全角度来看,我倾向于存储过程(MySQL从5.0开始就支持存储过程),其优点是-

大多数数据库(包括MySQL)允许将用户访问限制为执行存储过程。细粒度安全访问控制有助于防止特权攻击升级。这防止了受损的应用程序能够直接针对数据库运行SQL。它们从应用程序中提取原始SQL查询,因此应用程序可以获得的数据库结构信息较少。这使得人们更难理解数据库的底层结构并设计合适的攻击。它们只接受参数,因此参数化查询的优势就在这里。当然,IMO仍然需要清理输入,尤其是在存储过程中使用动态SQL时。

缺点是-

它们(存储过程)很难维护,而且往往会很快繁殖。这使得管理它们成为一个问题。它们不太适合动态查询——若构建它们是为了接受动态代码作为参数,那个么许多优点就被否定了。

对于那些不确定如何使用PDO(来自mysql_函数)的人,我制作了一个非常非常简单的PDO包装器,它是一个单独的文件。它的存在是为了显示应用程序需要做的所有常见事情是多么容易。适用于PostgreSQL、MySQL和SQLite。

基本上,在阅读手册的同时阅读它,了解如何在实际生活中使用PDO函数,从而使以所需格式存储和检索值变得简单。

我想要一列$count=数据库::列('SELECT count(*)FROM `user`');我想要一个数组(key=>value)结果(即,用于生成一个选择框)$pairs=数据库::pairs('SELECT `id',`username`FROM`user`');我想要单行结果$user=DB::行('SELECT*FROM`user`WHERE `id`=?',数组($user_id));我想要一系列结果$banned_users=DB::fetch('SELECT*FROM `user`WHERE `banned`=?',数组('RUE'));

PHP和MySQL有很多答案,但以下是针对PHP和Oracle的代码,用于防止SQL注入以及定期使用oci8驱动程序:

$conn = oci_connect($username, $password, $connection_string);
$stmt = oci_parse($conn, 'UPDATE table SET field = :xx WHERE ID = 123');
oci_bind_by_name($stmt, ':xx', $fieldval);
oci_execute($stmt);

使用PDO和准备好的查询。

($conn是PDO对象)

$stmt = $conn->prepare("INSERT INTO tbl VALUES(:id, :name)");
$stmt->bindValue(':id', $id);
$stmt->bindValue(':name', $name);
$stmt->execute();

我建议使用PDO(PHP数据对象)运行参数化SQL查询。

这不仅可以防止SQL注入,还可以加快查询速度。

而且,通过使用PDO而不是mysql_、mysqli_和pgsql_函数,可以使应用程序从数据库中抽象出一点,这是很少需要切换数据库提供程序的情况。