如果把用户输入到一个网页,将其插入到MySQL数据库,有机会离开了发生安全问题被称为SQL注入敞开。这一课将教如何帮助防止这种情况的发生,并帮助保护脚本和MySQL语句。
注入通常发生在处理一个用户输入,如他们的名字,而不是一个名字,他们给一个会在不知不觉中你的数据库上运行的MySQL语句。
永远不要信任用户提供的数据,只能验证后处理这些数据,作为一项规则,这是通过模式匹配。在下面的例子中,用户名被限制为字母数字字符加下划线的长度在8到20个字符之间 - 根据需要修改这些规则。
1
2
3
4
5
6
7
8
9
|
if (preg_match( "/^\w{8,20}$/" , $_GET[ 'username' ], $matches))
{
$result = mysql_query( "SELECT * FROM users
WHERE username=$matches[0]" );
}
else
{
echo "username not accepted" ;
}
|
为了说明这个问题,认为这是摘要:
1
2
3
|
// supposed input
$ name = "Qadir'; DELETE FROM users;" ;
mysql_query( "SELECT * FROM users WHERE name='{$name}'" );
|
函数调用应该是从用户表中的名称列的名称相匹配用户指定的检索记录。在正常情况下,名称只包含字母数字字符或空间,如字符串髂骨。但在这里,给$name通过附加一个全新的查询,调用数据库变成灾难:注入DELETE查询删除用户的所有记录。
幸运的是,如果使用MySQL,在mysql_query()函数不会允许查询堆叠,或在一个单一的函数调用执行多个查询。如果尝试到堆放查询则调用失败。
其他PHP数据库扩展,如SQLite和PostgreSQL则愉快地进行堆查询,执行在一个字符串中的所有的查询,并创建一个严重的安全问题。
防止SQL注入:
可以处理所有的转义字符巧妙的脚本语言,比如Perl和PHP。 PHP的MySQL扩展提供的函数mysql_real_escape_string()输入到MySQL的特殊字符进行转义。
1
2
3
4
5
6
|
if (get_magic_quotes_gpc())
{
$ name = stripslashes($ name );
}
$ name = mysql_real_escape_string($ name );
mysql_query( "SELECT * FROM users WHERE name='{$name}'" );
|
LIKE困境:
为了解决的LIKE问题,一个自定义的转义机制必须用户提供的%和_字符转换成文字。使用addcslashes()函数,让可以指定一个字符范围转义。
1
2
3
|
$sub = addcslashes(mysql_real_escape_string( "%something_" ), "%_" );
// $sub == \%something\_
mysql_query( "SELECT * FROM messages WHERE subject LIKE '{$sub}%'" );
|