SQL注入-宽字节注入

1. GBK编码

gbk为中文编码,是一种双字节编码,将两个字节编译为一个汉字,其中第一个字节称为高位字节,第二个字节称为低位字节。

编码范围
    高位81-FE
    低位40-FE

2.宽字节注入原理

2.1php测试代码

 
error_reporting(0);
$id = $_GET['id'];
$id = addslashes($id);               //过滤单引号等特殊字符
echo $id;                              //输出过滤后的输入值
echo '
'
; $con = mysql_connect('localhost','root','root'); if(!con) { die(mysql_error()); } mysql_select_db('test',$con); mysql_query('SET NAMES GBK'); //将mysql的character_set_client,connection,results设置为gbk编码 $sql = "SELECT * FROM users WHERE id='{$id}'"; echo $sql; //输出SQL语句 echo '
'
; $result = mysql_query($sql); $row = mysql_fetch_array($result); if($row) { echo "$row[0]"."~"."$row[1]"; } else { die(mysql_error()); } mysql_close($con) ?>

2.2测试

常规构造?id=1'使引号逃逸
发现失败了,引号被转义
SQL注入-宽字节注入_第1张图片
构造?id=1%81%27使引号逃逸
结果成功
SQL注入-宽字节注入_第2张图片

2.3原理

1.输入1%81%27
2.服务端对接受到的二进制数据进行解码,解码后的数据为1'
3.addslashes()函数对单引号进行转义,转义后结果为1�\'
4.数据传给MySQL,MySQL接受到的数据为10x815c27,MySQL对其进行解码,解码后为1'
5.执行SQL语句,语句为SELECT * FROM users WHERE id='乗'',单引号逃逸

补充:\的十六进制为0x5c
    乗的十六进制为0x815c

2.4表单提交与URL栏提交

如果在表单提交数据,数据中的%会进行URL编码
而从URL栏提交则不会对%再次编码
比如1%81%27从表单提交后,数据实际上是1%2581%2527
从表单提交的%被编码为%25
那么从表提交数据就不会触发宽字节注入

1.表单提交1%81%27
2.经URL编码后,提交的结果为1%2581%2527
3.服务端对接收到的数据进行解码,解码后为1%81%27
4.addslashes()函数对传入的参数没有需要转义的地方
5.数据最后传到MySQL中就是1%81%27

3.宽字节注入的防御措施

1.用mysql_real_escape_string()+mysql_set_charset('gbk')这种方式来过滤

mysql_set_charset('gbk',$con);
$id = mysql_real_escape_string($id);

2.用如下方式设置MySQL编码

mysql_query("SET character_set_client=binary,character_set_connection=gbk,character_set_results=gbk", $con);

你可能感兴趣的:(SQL注入)