古老的欺骗

要对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>&nbsp;</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>


参考文章:http://www.xfocus.net/articles/200107/237.html