📜  SQL-注入

📅  最后修改于: 2020-12-29 04:44:29             🧑  作者: Mango


如果您通过网页输入用户输入并将其插入到SQL数据库中,那么您就有可能对称为SQL Injection的安全问题敞开大门。本章将教您如何防止这种情况的发生,并帮助您保护服务器端脚本(例如PERL脚本)中的脚本和SQL语句。

通常,当您要求用户输入诸如名称之类的内容时,就会发生注入操作,并且他们会给您一条SQL语句(而不是名称),而您将在不知不觉中在数据库上运行该SQL语句。永远不要信任用户提供的数据,仅在验证后才处理这些数据;通常,这是通过Pattern Matching完成的。

在下面的示例中,名称限制为字母数字字符加下划线,长度限制为8至20个字符(根据需要修改这些规则)。

if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)) {
   $result = mysql_query("SELECT * FROM CUSTOMERS 
      WHERE name = $matches[0]");
} else {
   echo "user name not accepted";
}

为了演示问题,请考虑以下摘录-

// supposed input
$name = "Qadir'; DELETE FROM CUSTOMERS;";
mysql_query("SELECT * FROM CUSTOMSRS WHERE name='{$name}'");

该函数调用应该从CUSTOMERS表中检索一条记录,其中name列与用户指定的名称匹配。在正常情况下, $ name仅包含字母数字字符,可能还包含空格,例如字符串ilia。但是在这里,通过在$ name后面附加一个全新的查询,对数据库的调用变成了灾难。注入的DELETE查询将从CUSTOMERS表中删除所有记录。

幸运的是,如果使用MySQL,则mysql_query()函数不允许查询堆栈或在单个函数调用中执行多个SQL查询。如果您尝试堆叠查询,则调用将失败。

但是,其他PHP数据库扩展(例如SQLitePostgreSQL)愉快地执行堆叠查询,执行一个字符串提供的所有查询并造成严重的安全性问题。

防止SQL注入

您可以使用PERL和PHP等脚本语言来巧妙地处理所有转义字符。 PHP的MySQL扩展提供了函数mysql_real_escape_string()来转义MySQL特有的输入字符。

if (get_magic_quotes_gpc()) {
   $name = stripslashes($name);
}
$name = mysql_real_escape_string($name);
mysql_query("SELECT * FROM CUSTOMERS WHERE name='{$name}'");

像Quadary

为了解决LIKE难题,自定义转义机制必须将用户提供的’%’和’_’字符为字面量。使用addcslashes() ,该函数可让您指定要转义的字符范围。

$sub = addcslashes(mysql_real_escape_string("%str"), "%_");
// $sub == \%str\_
mysql_query("SELECT * FROM messages 
   WHERE subject LIKE '{$sub}%'");