如果用户输入未经修改就插入到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。从安全的角度来看,只要开发人员按照应该使用的方式使用它们,它们都是安全的

其他回答

安全警告:此答案不符合安全最佳实践。转义不足以防止SQL注入,请改用准备好的语句。使用以下概述的策略,风险自负。(此外,在PHP7中删除了mysql_real_ascape_string()。)不推荐使用警告:mysql扩展目前不推荐使用。我们建议使用PDO扩展

我使用三种不同的方法来防止我的web应用程序容易受到SQL注入的攻击。

使用mysql_real_aescape_string(),这是PHP中的一个预定义函数,此代码为以下字符添加反斜杠:\x00、\n、\r、\、'、“和\x1a。将输入值作为参数传递,以最大限度地减少SQL注入的机会。最先进的方法是使用PDO。

我希望这对你有帮助。

考虑以下查询:

$iId=mysql_real_ascape_string(“1或1=1”);$sSql=“SELECT*FROM table WHERE id=$iId”;

mysql_real_aescape_string()在这里不起保护作用。如果在查询中的变量周围使用单引号(“”),则可以防止这种情况发生。下面是一个解决方案:

$iId=(int)mysql_real_aescape_string(“1或1=1”);$sSql=“SELECT*FROM table WHERE id=$iId”;

这个问题有一些很好的答案。

我建议,使用PDO是最好的选择。

编辑:

自PHP 5.5.0起,mysql_real_aescape_string()已被弃用。使用mysqli或PDO。

mysql_real_aescape_string()的替代方法是

string mysqli_real_escape_string ( mysqli $link , string $escapestr )

例子:

$iId = $mysqli->real_escape_string("1 OR 1=1");
$mysqli->query("SELECT * FROM table WHERE id = $iId");

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

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

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

不推荐的警告:这个答案的示例代码(与问题的示例代码一样)使用了PHP的MySQL扩展,该扩展在PHP 5.5.0中被弃用,在PHP 7.0.0中被完全删除。安全警告:此答案不符合安全最佳实践。转义不足以防止SQL注入,请改用准备好的语句。使用以下概述的策略,风险自负。(此外,在PHP7中删除了mysql_real_ascape_string()。)重要的防止SQL注入的最佳方法是使用Prepared语句而不是转义,正如公认的答案所示。有Aura.Sql和EasyDB这样的库可以让开发人员更容易地使用准备好的语句。若要了解更多有关为什么准备好的语句更善于停止SQL注入的信息,请参阅此mysql_real_ascape_string()旁路以及最近修复的WordPress中的Unicode SQL注入漏洞。

注入预防-mysql_real_ascape_string()

PHP有一个专门制作的函数来防止这些攻击。您所需要做的就是使用一个函数,mysql_real_aescape_string。

mysql_real_aescape_string获取一个将在mysql查询中使用的字符串,并返回同一个字符串,所有SQL注入尝试都安全逃脱。基本上,它会将用户可能输入的那些麻烦的引号(')替换为MySQL安全的替代品,即转义引号“”。

注意:您必须连接到数据库才能使用此功能!

//连接到MySQL

$name_bad = "' OR 1'"; 

$name_bad = mysql_real_escape_string($name_bad);

$query_bad = "SELECT * FROM customers WHERE username = '$name_bad'";
echo "Escaped Bad Injection: <br />" . $query_bad . "<br />";


$name_evil = "'; DELETE FROM customers WHERE 1 or username = '"; 

$name_evil = mysql_real_escape_string($name_evil);

$query_evil = "SELECT * FROM customers WHERE username = '$name_evil'";
echo "Escaped Evil Injection: <br />" . $query_evil;

您可以在MySQL-SQL注入预防中找到更多详细信息。

我认为,在PHP应用程序(或任何web应用程序)中防止SQL注入的最佳方法是考虑应用程序的架构。如果防止SQL注入的唯一方法是记住使用一个特殊的方法或函数,它在每次与数据库对话时都会做正确的事情,那么这是错误的。这样,在代码的某个时刻忘记正确格式化查询只是时间问题。

采用MVC模式和CakePHP或CodeIgniter这样的框架可能是正确的方法:创建安全数据库查询等常见任务已在这些框架中得到解决并集中实现。它们可以帮助您以合理的方式组织web应用程序,并让您更多地考虑加载和保存对象,而不是安全地构造单个SQL查询。

安全警告:此答案不符合安全最佳实践。转义不足以防止SQL注入,请改用准备好的语句。使用以下概述的策略,风险自负。

你可以做一些基本的事情,比如:

$safe_variable = mysqli_real_escape_string($dbConnection, $_POST["user-input"]);
mysqli_query($dbConnection, "INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

这并不能解决所有问题,但它是一个很好的垫脚石。我省略了一些明显的项目,例如检查变量的存在性、格式(数字、字母等)。