要对PHP+Mysql的页面进行注射攻击是比较困难的,很大的原因是Mysql这个数据库功能不多,很多功能没有反倒加强了它的安全性。不过功能再怎么弱,程序上的漏洞还是不能免的,所以最近结合研究的PHP SQL Injuction 的一些问题,列举出相关可能存在的SQL安全漏洞。
php.ini中有一个参数叫 magic_quotes_gpc ,如果php.ini没有配置的默认情况下 magic_quotes_gpc=on。
它的作用是把所有从GET/POST/Cookie来的变量的单引号(‘)、双引号(“)、反斜杠backslash()以及空字元NULL(the null byte)都加上反斜杠,以使数据库能够正确查询。例如如果输入一个用户名是 a’b,传上来后反到变量里的值就是’a’b’,也就是说这个’还是存在于用户名变量中。
如果magic_quotes_gpc=off情况就不同了,这就是sql injuction有机可乘的时候。
如果原查询语句是这样的:
select * from login where user=’$HTTP_POST_VARS[user]’ and pass=’$HTTP_POST_VARS[pass]’
我们就可以在用户框和密码框输入 1′ or 1=’1 通过验证了。这是非常古董的方法了,这个语句会替换成这样:
select * from login where user=’1′ or 1=’1′ and pass=’1′ or 1=’1′
因为or 1=’1’成立,所以通过了。
解决的办法一:过滤所有不必要的字符,还有就是推荐对于从GET/POST/Cookie来的并且用在SQL中的变量加一个自定义的函数:
function gpc2sql($str) {
if(get_magic_quotes_gpc()==1)
return $str;
else
return addslashes($str);
}
解决办法二:不要用select * from login这种验证用户的方式,最好用select password from login where username=’$username’,然后再比较一下password是否相等,也同样可以避免这个注入的发生。
测试页面代码:
<?
if(isset($HTTP_POST_VARS[‘username’]))
{
$username = $HTTP_POST_VARS[‘username’];
$password = $HTTP_POST_VARS[‘password’];
include(“db.php”);
$db = mysql_connect($db_host,$db_user,$db_password);
mysql_select_db($db_name,$db);
$result = mysql_query(“SELECT * FROM table1 where name=’$username’ and password=’$password'”);
$row=mysql_fetch_array($result);
if($row)
{
$info = “login successfully.”;
}
else
{
$info = “login fail.”;
}
}
?>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN” >
<HTML>
<HEAD>
<TITLE>Login</TITLE>
<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″>
</HEAD>
<BODY bgcolor=”#F3F3F3″>
<table width=”450″ border=”0″ cellspacing=”0″ cellpadding=”0″ align=”left”>
<tr>
<td valign=”top” width=”130″></td>
<td width=”320″>
<br>
<br>
<br>
<table width=”300″ border=”0″ cellspacing=”0″ cellpadding=”0″ bgcolor=”#F3F3F3″>
<tr>
<td>
<form name=”entry” method=”post” action=”postback.php”>
<table border=”0″ cellspacing=”0″ cellpadding=”3″ width=”100%”>
<tr valign=”top”>
<td colspan=4> <b>please log in: </b><br/>
<?
if(isset($info))
{echo($info);}
?>
</td>
</tr>
<tr valign=”top”>
<td><br><br>user:</td>
<td><br><br>
<input type=”text” name=”username” tabindex=”1″ size=”10″ maxlength=”10″>
</td>
<td><br><br>pass:</td>
<td><br><br>
<input type=”password” name=”password” tabindex=”2″ size=”10″ maxlength=”30″ >
</td>
</tr>
<tr valign=”top”>
<td> </td>
<td colspan=”3″>
<input type=”image” border=”0″ name=”login” value=”login” width=”22″ height=”12″ alt=”press enter”>
<input type=”image” border=”0″ value=”reset” name=”reset” width=”40″ height=”12″ alt=”reset form”>
</td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</td>
</tr>
</table>
</BODY>
</HTML>