PHP中防止SQL注入攻击

字体大小: 中小 标准 ->行高大小: 标准
  SQL injection问题在ASP上可是闹得沸沸扬扬 当然还有不少国内外著名的PHP程序“遇难”。至于SQL injection的详情,网上的文章太多了,在此就不作介绍。如果你网站空间的php.ini文件里的magic_quotes_gpc设成了off,那么PHP就不会在敏感字符前加上反斜杠(\),由于表单提交的内容可能含有敏感字符,如单引号("),就导致了SQL injection的漏洞。在这种情况下,我们可以用addslashes()来解决问题,它会自动在敏感字符前添加反斜杠。

    但是,上面的方法只适用于magic_quotes_gpc=Off的情况。作为一个开发者,你不知道每个用户的magic_quotes_gpc是On 还是Off,如果把全部的数据都用上addslashes(),那不是“滥杀无辜”了?假如magic_quotes_gpc=On,并且又用了 addslashes()函数,那让我们来看看:

    罪恶之源:用户提交过来的数据是可靠的。 
  
    用户可以伪造表单和URL提交他想提交的任何数据,如果你把他提交过来的数据变量直接联入sql语句就会造成注入,一般性的防范措施是:
   
    所有sql语句必须用单引号,因为单引号内的字符串只有两个特殊,它自己和转义符,只要搞定这两个就ok了,而addslashes完全胜任,php.ini里magic_quotes_gpc默认是off的,有的是on的,这就需要在使用addslashes之前ini_get一下看这个设置是on还是off然后再决定是否用,mysql的sql语句的组成中一般只有整形和字符型,整形加上引号也不会出错,如果嫌麻烦就全加上引号,更安全一点就是inval()转化成整形。这样处理基本就没问题了,至于是否允许提交html代码看你要求了,不允许的话就用函数去掉<>   
    
    更安全一点的遍历post,get,cookie,对他们的长度进行控制,addslashes,去除html(或转化成&),图片验证码,表单的http   refferring、session_id判断,更高级的是表单过期判断(一般用某个常量和时间算出的hash,提交的时候再验证这个hash)。   
    
    随着$_POST类变量的普及使用,php的安全性得到了很大提高,再注意一下单引号和addslashes,基本就是固若金汤了
  
CODE:<?php
//如果从表单提交一个变量$_POST["message"],内容为 Tom"s book
//这此加入连接MySQL数据库的代码,自己写吧
//在$_POST["message"]的敏感字符前加上反斜杠
$_POST["message"] = addslashes($_POST["message"]);

//由于magic_quotes_gpc=On,所以又一次在敏感字符前加反斜杠
$sql = "INSERT INTO msg_table VALUE("$_POST[message]");";

//发送请求,把内容保存到数据库内
$query = mysql_query($sql);

//如果你再从数据库内提取这个记录并输出,就会看到 Tom\"s book
?>

    这样的话,在magic_quotes_gpc=On的环境里,所有输入的单引号(")都会变成(\")…….其实我们可以用get_magic_quotes_gpc()函数轻易地解决这个问题。当magic_quotes_gpc=On时,该函数返回 TRUE;当magic_quotes_gpc=Off时,返回FALSE。至此,肯定已经有不少人意识到:问题已经解决。请看代码:

CODE:<?php
//如果magic_quotes_gpc=Off,那就为提单提交的$_POST["message"]里的敏感字符加反斜杠
//magic_quotes_gpc=On的情况下,则不加
if (!get_magic_quotes_gpc()) {
$_POST["message"] = addslashes($_POST["message"]);
} else {}
?>

    其实说到这里,问题已经解决。下面再说一个小技巧。
有时表单提交的变量不止一个,可能有十几个,几十个。那么一次一次地复制/粘帖addslashes(),是否麻烦了一点?由于从表单或URL获取的数据都是以数组形式出现的,如$_POST、$_GET) 那就自定义一个可以“横扫千军”的函数:

CODE:<?php
function quotes($content)
{
//如果magic_quotes_gpc=Off,那么就开始处理
if (!get_magic_quotes_gpc()) {
//判断$content是否为数组
if (is_array($content)) {
//如果$content是数组,那么就处理它的每一个单无
foreach ($content as $key=>$value) {
$content[$key] = addslashes($value);
}
} else {
//如果$content不是数组,那么就仅处理一次
addslashes($content);
}
} else {
//如果magic_quotes_gpc=On,那么就不处理
}
//返回$content
return $content;
}
?>

此文章由 www.phpgz.com 收集整理 ,地址为: http://www.phpgz.com/htmls/68632.html

大屏阅读,大屏评论.