PHP所有打印的语句如echo,print 等,在打印前都要使用htmlentities() 进行过滤,

这样可以防止Xss,注意中文字符要写出

htmlentities($name, ENT_NOQUOTES, GB2312);

 

mysql_real_escape_string() 

所以SQL语句如果有类似这样的写法:

"select * from cdr where src =" . $userId;

都要改成

$userId=mysql_real_escape_string($userId) 

PHP mysql_real_escape_string() 函数

定义和用法

mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。

下列字符受影响:

  • \x00
  • \n
  • \r
  • \
  • '
  • "
  • \x1a

如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。

语法

mysql_real_escape_string(string,connection)
参数 描述
string 必需。规定要转义的字符串。
connection 可选。规定 MySQL 连接。如果未规定,则使用上一个连接。

说明

本函数将 string 中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()

示例1:

<?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);
?>

示例2:

数据库攻击。本例演示如果我们不对用户名和密码应用 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 ''=''

这意味着任何用户无需输入合法的密码即可登陆。

示例3:

预防数据库攻击的正确做法:

<?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);
?>

 

PHP防范SQL注入

PHP防范SQL注入是一个非常重要的安全手段。

一个优秀的PHP程序员,除了要能顺利的编写代码,还需要具备使程序处于安全环境下的能力。

说到网站安全就不得不提到SQL注入(SQL Injection),如果你用过ASP,对SQL注入一定有比较深的理解,PHP的安全性相对较高,这是因为MYSQL4以下的版本不支持子语句,而且当php.ini里的 magic_quotes_gpc 为On 时。

提交的变量中所有的‘ (单引号), ” (双引号),\ (反斜线) and 空字符,会自动转为含有反斜线的转义字符,给SQL注入带来不少的麻烦

 

请看清楚:

“麻烦”而已,这并不意味着PHP防范SQL注入,书中就讲到了利用改变注入语句的编码来绕过转义的方法,比如将SQL语句转成ASCII编码(类似:char(100,58,92,108,111,99,97,108,104,111,115,116…)这样的格式),或者转成16进制编码,甚至还有其他形式的编码。

这样以来,转义过滤便被绕过去了,那么怎样防范呢?

 

a. 打开magic_quotes_gpc或使用addslashes()函数

在新版本的PHP中,就算 magic_quotes_gpc 打开了,再使用 addslashes() 函数,也不会有冲突,但是为了更好的实现版本兼容,建议在使用转移函数前先检测magic_quotes_gpc状态,或者直接关掉。

如何打开magic_quotes_gpc来防止SQL注入?

SQL注入是非常危险的事情,轻则网站后台被入侵,重则整个服务器沦陷,所以用户一定要小心。那么该如何防止SQL的注入呢?

方法1) php.ini中有一个设置

; magic_quotes_gpc = Off 
magic_quotes_gpc = On

该设置默认是关闭的(Off),如果它打开后将自动把用户提交对sql的查询进行转换,例如把""转换为"\'"等,这对防止sql注入有重大作用,所以我们将magic_quotes_gpc设置为On

PHP 防范SQL注入的示例代码

// 去除转义字符
function stripslashes_array($array) {
	if (is_array($array)) {
		foreach ($array as $k => $v) {
			$array[$k] = stripslashes_array($v);
		}
	} else if (is_string($array)) {
		$array = stripslashes($array);
	}
	return $array;
}

@set_magic_quotes_runtime(0);

// 判断 magic_quotes_gpc 状态
if (@get_magic_quotes_gpc()) {
	$_GET = stripslashes_array($_GET);
	$_POST = stripslashes_array($_POST);
	$_COOKIE = stripslashes_array($_COOKIE);
} 

 

PHP 防范SQL注入的代码

去除magic_quotes_gpc的转义之后再使用 addslashes() 函数,代码如下:

$keywords = addslashes($keywords); 
$keywords = str_replace("_","\_",$keywords);	//转义掉 "_" 
$keywords = str_replace("%","\%",$keywords);	//转义掉 "%"

后两个str_replace替换转义目的是防止黑客转换SQL编码进行攻击。

 

b. 强制字符格式(类型)

在很多时候我们要用到类似 xxx.php?id=xxx 这样的URL,一般来说$id都是整型变量

为了防范攻击者把$id篡改成攻击语句,我们要尽量强制变量,代码如下:

PHP防范SQL注入的代码

$id=intval($_GET['id']);

当然,还有其他的变量类型,如果有必要的话尽量强制一下格式。

 

c. SQL语句中包含变量加引号

这一点儿很简单,但也容易养成习惯,先来看看这两条SQL语句:

SELECT * FROM article WHERE articleid='$id'; 
SELECT * FROM article WHERE articleid=$id;

两种写法在各种程序中都很普遍,但安全性是不同的,

第一句由于把变量$id放在一对单引号中,这样使得我们所提交的变量都变成了字符串,即使包含了正确的SQL语句,也不会正常执行,

第二句不同,由于没有把变量放进单引号中,那我们所提交的一切,只要包含空格,那空格后的变量都会作为SQL语句执行,因此,我们要养成给SQL语句(不是PHP语句)中变量加引号的习惯。

 

d. URL伪静态化

URL伪静态化也就是URL重写技术,像Discuz!一样,将所有的URL都rewrite成类似xxx-xxx-x.html格式,既有利于SEO,又达到了一定的安全性,也不失为一个好办法。但要想实现PHP防范SQL注入,前提是你得有一定的“正则”基础。

 

 

参考推荐

PHP防止SQL注入的方法

PHP中防止SQL注入实现代码

php mysql防止sql注入详细说明

PHP中防止SQL注入的最佳解决方法

通用的关于sql注入的绕过技巧