1. 强制字符格式(类型)
在很多时候我们要用到类似xxx.php?id=xxx这样的URL,一般来说$id都是整型变量,为了防攻击者把$id篡改成攻击语句,要尽量强制变量,代码如下:
PHP防SQL注入的代码:
$id = intval ($_GET[‘id’]);
当然,还有其它的变量类型,如果有必要的话尽量强制一下格式。
2. SQL语句中包含变量加引号
这一点很简单,但也容易养成相关,先来看看这两条SQL语句:
SQL代码:
SELECT * FROM article WHERE articleid = ‘$id’
SELECT * FROM article WHERE articleid = $id
两种写法在各种程序中都很普遍,但安全性是不同的,第一句由于把变量$id放在一对单引号中,这样使得我们所提交的变量都变成了字符串,即使包含了正确的SQL语句,也不会正常执行,而第二句不同,由于没有把变量放进单引号中,那我们所提交的一切,只要包含空格,那空格后的变量都会作为SQL语句执行,因此,我们要养成给SQL语句中变量加引号的习惯。
3. URL伪静态化
URL伪静态化也就是URL重写技术,像Discuz!一样,将所有的URL都rewrite成类似xxx-xxx-x.html格式,即有利于SEO,又达到了一定的安全性,也不失为一个好办法。但是想实现PHP防SQL注入,前提是你得有一定的“正则”基础。
4. 用PHP函数过滤与转义
PHP的SQL注入比较重要的一点就是GPC的设置问题,因为MYSQL4以下的版本是不支持子语句的,而且当php.ini里的magic_quotes_gpc为On时,提交的变量中所有的 “ ‘ ”(单引号)、“ ” ”(双引号)、“ \ ”(反斜线)和空字符都会自动转为含有反斜线的转义字符,给SQL注入带来不少的阻碍。
5. 用PHP的MySQL函数过滤与转义
PHP的MySQL操作函数中有addslashes()、mysql_real_escape_string()、mysql_escape_string()等函数,可将特殊字符或可能引起数据库操作出错的字符转义。
那么这三个功能函数之间有什么区别呢?下面我们来详细讲述下:
① addslashes的问题在于黑客可以用0xbf27来代替单引号,而addslashes只是将0xbf27修改为0xbf5c27,称为一个有效的多字节字符,其中0xbf5c仍会被看做是单引号,所以addslashes无法成功拦截。
当然addslashes也不是毫无用处,它是用于单字节字符串的处理,多字节字符还是用mysql_real_escape_string吧。
另外对于php手册中get_magic_quotes_gpc的举例:
if(!get_magic_quotes_gpc()){ $lastname = addslashes($_POST['lastname']); }else{ $lastname = $_POST['lastname']; }
最好对magic_quotes_gpc已经打开的情况下,还是对$_POST[‘lastname’]进行检查一下。
再说下mysql_real_escape_string和mysql_escape_string这2个函数的区别:
- mysql_real_escape_string必须在(PHP 4 >= 4.3.0, PHP 5)的情况下才能使用。否则只能用mysql_escape_string。
- mysql_real_escape_string考虑到连接的当前字符集,而mysql_escape_string不考虑。
discuz的防止sql注入就是用addslashes这个函数:
function daddslashes($string, $force = 0, $strip = FALSE) { if(!MAGIC_QUOTES_GPC || $force) { if(is_array($string)) { foreach($string as $key => $val) { $string[$key] = daddslashes($val, $force, $strip); } } else { $string = addslashes($strip ? stripslashes($string) : $string); } } return $string; }