1. php 配置文件 php.ini 中的 magic_quotes_gpc选项没有打开,被置为 off;
2. 没有对数据类型进行检查和转义。
一、 magic_quotes_gpc = Off 时的注入攻击
magic_quotes_gpc = Off 是 php 中一种非常不安全的选项。新版本的 php 已经将默认的值改为了 On。但仍有相当多的服务器的选项为 off。当magic_quotes_gpc = On 时,它会将提交的变量中所有的 '(单引号)、"(双号号)、(反斜线)、空白字符,都会在前面自动加上 。
如果攻击者在 username 字段中输入:zhang3' OR 1=1 #,在 password 输入 abc123,则提交的 SQL 语句变成如下:
SELECT * FROM tbl_users
WHERE username='zhang' OR 1=1 #' AND password = '123' LIMIT 0,1;
由于 # 是 mysql中的注释符, #之后的语句不被执行,实现上这行语句就成了:
SELECT * FROM tbl_users
WHERE username='zhang3' OR 1=1;
如果agic_quotes_gpc选项为 on,引号被转义
二、magic_quotes_gpc = On 时的注入攻击
当 magic_quotes_gpc = On 时,攻击者无法对字符型的字段进行 SQL 注入。这并不代表这就安全了。这时,可以通过数值型的字段进行SQL注入。
如果攻击者在 userid 处,输入:1001 OR 1 =1 #,则注入的sql语句如下:
SELECT * FROM tbl_users WHERE userid=1001 OR 1 =1 # AND password = 'abc123' LIMIT 0,1;
三、如何防止 PHP的SQL 注入攻击
1. php.ini 中的 display_errors 选项,应该设为display_errors = off。这样 php 脚本出错之后,不会在 web 页面输出错误,以免让攻击者分析出有作的信息。
2. 调用 mysql_query 等 mysql 函数时,前面应该加上 @,即 @mysql_query(...),这样 mysql 错误不会被输出。同理以免让攻击者分析出有用的信息。
3.PHP的MySQl扩展提供了mysqli_real_escape_string()函数来转义特殊的输入字符。
预防数据库攻击的正确做法:
<?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); ?>
4.Like语句中的注入
like查询时,如果用户输入的值有"_"和"%",则会出现这种情况:用户本来只想查询"abcd_",查询结果中却有"abcd_"、"abcd"、"abcdf"等等;用户要查询"30%"(百分之三十)时也会出现问题。在PHP脚本中可以使用addcslashes()函数来处理以上情况
在PHP脚本中可以使用addcslashes()函数来处理以上情况,如下实例:
$sub = addcslashes(mysqli_real_escape_string($conn, "%something_"), "%_"); // $sub == \%something\_ mysqli_query($conn, "SELECT * FROM messages WHERE subject LIKE '{$sub}%'");
addcslashes()函数在指定的字符前添加反斜杠。