SQL 注入

SQL 注入

如果你通过网页接收用户输入并将其插入到SQL数据库中,那么你可能会给自己留下一个被攻击的安全漏洞,称为 SQL注入 。本章将教你如何预防这种情况发生,并帮助你在服务器端脚本(如PERL脚本)中保护脚本和SQL语句的安全。

注入通常发生在你要求用户提供输入的时候,比如他们的名字,但他们给你的却是一个你会无意中在数据库上运行的SQL语句。不要相信用户提供的数据,仅在验证后处理这些数据;常规情况下,这是由 模式匹配 完成的。

在下面的示例中, 名称 被限制为字母数字字符加下划线,并且长度在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匹配。在正常情况下,name可能只包含字母数字字符和空格,比如字符串ilia。但是在这里,通过向name添加一个全新的查询,对数据库的调用变成了一场灾难;注入的DELETE查询会删除CUSTOMERS表中的所有记录。

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

然而,其他PHP数据库扩展,如SQLite和PostgreSQL,乐意执行堆叠查询,以一个字符串执行所有提供的查询,从而创建严重的安全问题。

防止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}'");

LIKE困境

为了解决LIKE的困境,我们需要使用一种自定义的转义机制将用户提供的’%’和’_’字符转换为字面值。可以使用 addcslashes() 函数来指定要转义的字符范围。

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

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程