mysql宽字节数_Mysql宽字节注入 · BlBana’s BlackHouse

本文探讨了SQL注入中字符编码GB2312和GBK的区别,以及mysql_real_escape_string和iconv函数如何影响注入。重点介绍了如何通过设置字符集、使用mysql_set_charset和避免宽字节注入的方法来保障数据库安全。
摘要由CSDN通过智能技术生成

字符集简介

GBK是一种多字符的编码,通常来说,一个gbk编码汉字,占用2个字节。一个utf-8编码的汉字,占用3个字节。当将页面编码保存为gbk时输出2,utf-8时输出3。除了gbk以外,所有ANSI编码都是2个字节。现在我们来研究一下SQL注入中,字符编码带来的问题。

开始测试

0x01 Mysql中宽字节注入

实例代码如下:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24$conn = mysql_connect('localhost', 'root', '07191226') or die('bad!');

mysql_query("SET NAMES 'gbk'");

mysql_select_db('test', $conn) OR die("连接数据库失败,未找到您填写的数据库");

//执行sql语句

$id = isset($_GET['id']) ? addslashes($_GET['id']) : 1;

$sql = "SELECT * FROM news WHERE tid='{$id}'";

$result = mysql_query($sql, $conn) or die(mysql_error()); //sql出错会报错,方便观察

?>

新闻

$row = mysql_fetch_array($result, MYSQL_ASSOC);

echo "

{$row['title']}

{$row['content']}

n";

mysql_free_result($result);

?>

在这个语句中,使用了addslashes函数,将我们输入的$id进行了转义。

现在我们对这个脚本进行SQL注入测试,先加上一个单引号:

ca79489fa9dd9811b66be5fee2384cd0.png

正常的显示,没有报错,说明addslashes起到了作用,我们的单引号被转义了,没有起到作用。这个时候如果想要逃过addslashes的限制,我们有两种办法:1.想办法让前再加一个,这样就成了‘,被转义,‘逃出了限制;

2.先办法把弄没有。

这里就可以利用宽字节注入来进行绕过,mysql在使用GBK编码的时候,会认为两个字符是一个汉字,当我们输入%df的时候:

e578604f4828a7506d658dc2ed96a647.png

发现出现了报错,说明我们的语句已经影响了正常语句的执行了,可以注入了。这里为什么加一个%df就可以了呢?因为这是mysql的一种特性,GBK是多字节编码,它认为两个字节就代表一个汉字,在%df加入的时候会和转义符,即%5c进行结合,变成了一个“運”,而’逃逸了出来。

因此只要第一个字节和%5c结合是一个汉字,就可以成功绕过了,当第一个字节的ascii码大于128,就可以了。

0x02 GB2312测试

gb2312和GBK一样属于宽字节,我们尝试一下gb2312能否绕过。1

2

3

4

5

6

7

8

9

10$conn = mysql_connect('localhost', 'root', '07191226') or die('bad!');

mysql_query("SET NAMES 'gb2312'");

mysql_select_db('test', $conn) OR die("连接数据库失败,未找到您填写的数据库");

//执行sql语句

$id = isset($_GET['id']) ? addslashes($_GET['id']) : 1;

$sql = "SELECT * FROM news WHERE tid='{$id}'";

$result = mysql_query($sql, $conn) or die(mysql_error()); //sql出错会报错,方便观察

?>

测试发现已经不可以注入了:

3ea901193817140cfe696fb577c94f0c.png

这是因为gb2312的取值范围。高位的范围是0xA1~0xF7,低位范围是0xA1~0xFE,是0x5C,不在地位的范围中。所以在编码中,’不会被吃掉,就无法造成注入了。

0x03 测试mysql_real_escape_string

mysql_real_escape_string,函数在使用的时候一定要考虑到当前字符集(mysql_set_charset)

现在将源码中的addslashes替换成mysql_real_escape_string,来尝试一下。1

2

3

4

5

6

7

8

9

10$conn = mysql_connect('localhost', 'root', '07191226') or die('bad!');

mysql_query("SET NAMES 'gb2312'");

mysql_select_db('test', $conn) OR die("连接数据库失败,未找到您填写的数据库");

//执行sql语句

$id = isset($_GET['id']) ? mysql_real_escape_string($_GET['id']) : 1;

$sql = "SELECT * FROM news WHERE tid='{$id}'";

$result = mysql_query($sql, $conn) or die(mysql_error()); //sql出错会报错,方便观察

?>

a4513e081e5bef3ea6e314d14ca8ba84.png

同样可以造成注入,这主要是因为没有指定php连接mysql时的字符集。我们需要在执行SQL语句前加上一个mysql_set_charset函数,设置当前字符集为gbk。

mysql_set_charset('gbk' , $conn);

这样子就可以避免注入了。

0x04 防止宽字节注入

一种方法就是先调用mysql_set_charset设置当前字符集为gbk,再调用函数mysql_real_escape_string来过滤用户输入。

还可以把character_set_client设置为binary二进制

当我们的mysql接受到客户端的数据后,会认为他的编码是character_set_client,然后会将之将换成character_set_connection的编码,然后进入具体表和字段后,再转换成字段对应的编码。然后,当查询结果产生后,会从表和字段的编码,转换成character_set_results编码,返回给客户端。

0x05 iconv导致注入

使用函数iconv('utf-8','gbk',$_GET['id']),也可能导致注入产生。

虽然character_set_client设置成了binary,但是之后参数又被变回了gbk,我们可以使用“ 錦’ ”来进行注入:

48d1e3029060fbfb64941e0b907f49f2.png

这是因为錦’的GBK编码为0xe55c,所以就能发现后面为%5c%27,这个时候会出现两个%5c,刚好,反斜杠被转义,导致‘逃出造成了注入

0x06 总结

这里也发现,我们在编程的过程中尽量使用UTF-8的编码,从而避免宽字节的注入。即使使用GBK编码,也一定要做好防范:1.设置character_set_client=binary;

2.单独的使用set names gbk或者mysql_real_escape_string时也需要使用mysql_set_charset来设置一下字符集;

3.尽量不要使用iconv来转换字符编码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值