标签:
如果您通过网页获取用户输入的数据并将其插入一个MySQL数据库,那么就有可能发生SQL注入安全的问题。
本章节将为大家介绍如何防止SQL注入,并通过脚本来过滤SQL中注入的字符。
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
我们永远不要信任用户的输入,我们必须认定用户输入的数据都是不安全的,我们都需要对用户输入的数据进行过滤处理。
以下实例中,输入的用户名必须为字母、数字及下划线的组合,且用户名长度为 8 到 20 个字符之间:
if (preg_match("/^\w{8,20}$/", $_GET[‘username‘], $matches)) { $result = mysql_query("SELECT * FROM users WHERE username=$matches[0]"); } else { echo "username 输入异常"; }
让我们看下在没有过滤特殊字符时,出现的SQL情况:
// 设定$name 中插入了我们不需要的SQL语句 $name = "Qadir‘; DELETE FROM users;"; mysql_query("SELECT * FROM users WHERE name=‘{$name}‘");
以上的注入语句中,我们没有对 $name 的变量进行过滤,$name 中插入了我们不需要的SQL语句,将删除 users 表中的所有数据。
在PHP中的 mysql_query() 是不允许执行多个SQL语句的,但是在 SQLite 和 PostgreSQL 是可以同时执行多条SQL语句的,所以我们对这些用户的数据需要进行严格的验证。
防止SQL注入,我们需要注意以下几个要点:
在脚本语言,如Perl和PHP你可以对用户输入的数据进行转义从而来防止SQL注入。
PHP的MySQL扩展提供了mysql_real_escape_string()函数来转义特殊的输入字符。
if (get_magic_quotes_gpc()) { $name = stripslashes($name); } $name = mysql_real_escape_string($name); mysql_query("SELECT * FROM users WHERE name=‘{$name}‘");
like查询时,如果用户输入的值有"_"和"%",则会出现这种情况:用户本来只是想查询"abcd_",查询结果中却有"abcd_"、"abcde"、"abcdf"等等;用户要查询"30%"(注:百分之三十)时也会出现问题。
在PHP脚本中我们可以使用addcslashes()函数来处理以上情况,如下实例:
$sub = addcslashes(mysql_real_escape_string("%something_"), "%_"); // $sub == \%something\_ mysql_query("SELECT * FROM messages WHERE subject LIKE ‘{$sub}%‘");
addcslashes() 函数在指定的字符前添加反斜杠。
语法格式:
addcslashes(string,characters)
参数 | 描述 |
---|---|
string | 必需。规定要检查的字符串。 |
characters | 可选。规定受 addcslashes() 影响的字符或字符范围。 |
具体应用可以查看:PHP addcslashes() 函数
附录
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:
如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。
mysql_real_escape_string(string,connection)
参数 | 描述 |
---|---|
string | 必需。规定要转义的字符串。 |
connection | 可选。规定 MySQL 连接。如果未规定,则使用上一个连接。 |
本函数将 string 中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()。
提示:可使用本函数来预防数据库攻击。
<?php $con = mysql_connect("localhost", "hello", "321"); if (!$con) { die(‘Could not connect: ‘ . mysql_error()); } // 获得用户名和密码的代码 // 转义用户名和密码,以便在 SQL 中使用 $user =mysql_real_escape_string($user)
; $pwd =mysql_real_escape_string($pwd)
; $sql = "SELECT * FROM users WHERE user=‘" . $user . "‘ AND password=‘" . $pwd . "‘" // 更多代码 mysql_close($con); ?>
数据库攻击。本例演示如果我们不对用户名和密码应用 mysql_real_escape_string() 函数会发生什么:
<?php $con = mysql_connect("localhost", "hello", "321"); if (!$con) { die(‘Could not connect: ‘ . mysql_error()); } $sql = "SELECT * FROM users WHERE user=‘{$_POST[‘user‘]}‘ AND password=‘{$_POST[‘pwd‘]}‘"; mysql_query($sql); // 不检查用户名和密码 // 可以是用户输入的任何内容,比如: $_POST[‘user‘] = ‘john‘; $_POST[‘pwd‘] = "‘ OR ‘‘=‘"; // 一些代码... mysql_close($con); ?>
那么 SQL 查询会成为这样:
SELECT * FROM users WHERE user=‘john‘ AND password=‘‘ OR ‘‘=‘‘
这意味着任何用户无需输入合法的密码即可登陆。
预防数据库攻击的正确做法:
<?php function check_input($value) { // 去除斜杠 if (get_magic_quotes_gpc()) { $value =stripslashes($value)
; } // 如果不是数字则加引号 if (!is_numeric($value)) { $value = "‘" .mysql_real_escape_string($value)
. "‘"; } return $value; } $con = mysql_connect("localhost", "hello", "321"); if (!$con) { die(‘Could not connect: ‘ . mysql_error()); } // 进行安全的 SQL $user = check_input($_POST[‘user‘]); $pwd = check_input($_POST[‘pwd‘]); $sql = "SELECT * FROM users WHERE user=$user AND password=$pwd"; mysql_query($sql); mysql_close($con); ?>
addcslashes() 函数在指定的字符前添加反斜杠。
addcslashes(string,characters)
参数 | 描述 |
---|---|
string | 必需。规定要检查的字符串。 |
characters | 可选。规定受 addcslashes() 影响的字符或字符范围。 |
注释:在对 0,r,n 和 t 应用 addcslashes() 时要小心。在 PHP 中,\0,\r,\n 和 \t 是预定义的转义序列。
在本例中,我们要向字符串中的特定字符添加反斜杠:
<?php $str = "Hello, my name is John Adams."; echo $str; echoaddcslashes($str,‘m‘);
echoaddcslashes($str,‘J‘);
?>
输出:
Hello, my name is John Adams. Hello, \my na\me is John Ada\ms. Hello, my name is \John Adams.
在本例中,我们要向字符串中的一个范围内的字符添加反斜杠:
<?php $str = "Hello, my name is John Adams."; echo $str; echoaddcslashes($str,‘A..Z‘)
; echoaddcslashes($str,‘a..z‘)
; echoaddcslashes($str,‘a..h‘)
; ?>
输出:
Hello, my name is John Adams. \Hello, my name is \John \Adams. H\e\l\l\o, \m\y \n\a\m\e \i\s J\o\h\n A\d\a\m\s. H\ello, my n\am\e is Jo\hn A\d\ams.
标签:
原文地址:http://www.cnblogs.com/richerdyoung/p/4352992.html