一.前言
本章节来和大家讲解一下宽字节注入,这个宽字节注入也是有专门的情况才能使用,他得是GBK编码才行,大家还是点赞关注加收藏,期待大家的关注。
二.宽字节注入
2.1 编码
Url编码通常也被称为百分号编码(Url Encoding,also known as percent-encoding),是因为它的编 码方式非常简单,使用%百分号加上两位的字符——0123456789ABCDEF——代表一个字节的 十六进制 形式。Url编码默认使用的字符集是US-ASCII。例如a在US-ASCII码中对应的字节是0x61,那么Url编码之 后得到的就 是%61,我们在地址栏上输入http://g.cn/search?q=%61%62%63,实际上就等同于在google上搜索abc了。又如@符号 在ASCII字符集中对应的字节为0x40,经过Url编码之后得到的 是%40。
对于非ASCII字符,需要使用ASCII字符集的超集进行编码得到相应的字节,然后对每个字节执行百 分号编码。对于Unicode字 符,RFC文档建议使用utf-8对其进行编码得到相应的字节,然后对每个字节 执行百分号编码。如"中文"使用UTF-8字符集得到的字节为0xE4 0xB8 0xAD 0xE6 0x96 0x87,经过Url编码之后得到"%E4%B8%AD%E6%96%87"。
如果某个字节对应着ASCII字符集中的某个非保留字符,则此字节无需使用百分号表示。例如"Url编 码",使用UTF-8编码得到的字节是 0x55 0x72 0x6C 0xE7 0xBC 0x96 0xE7 0xA0 0x81,由于前三个字 节对应着ASCII中的非保留字符"Url",因此这三个字节可以用非保留字符"Url"表示。最终的Url编码可以 简化 成"Url%E7%BC%96%E7%A0%81" ,当然,如果你用"%55%72%6C%E7%BC%96%E7%A0%81"也 是可以的。
其中%27其实就是我们的一个 ' 单引号,空格自动转换为 + 加号,而url编码默认使用的字符集编码为ascii码,那么%27其实就是一个十六进制的字节0x27,当然也是可以改的,在meta标签中可以声明编 码方式,GBK或者GB2312等,中文是由两个字节(16进制)表示的,utf是3个字节表示的,所有由于各种 原因吧,很多网站使用的编码不同,有的是gbk,有的是utf8,gbk看上去省了一些存储空间,但是现在 多数的网站基本都是utf8了,因为兼容性更好一些。这里我就不细说了。
2.2 注入防御之引号转义和绕过思路
好多网站,尤其是php的网站,为了防止sql注入,经常会采用一个手段就是引号转义,比如开启全局GPC配置,如下phpstudy中开启:
也就是php.ini配置文件中添加magic_quotes_gpc=on。
或者是使用一些转义函数,比如:addslashes和mysql_real_escape_string,他们转义的字符是单引号(')、双引号(")、反斜线()与NUL(NULL 字符),转义的方式就是在这些符号前面自动加上 \ ,让这些符号 的意义失效,或者可以理解为被注释掉了。
编码转换工具:
那么我们的sql注入语句就跟着失效了,因为好多时候,我们写注入语句难免会使用到引号等特殊符号, 比如下面这个
http://192.168.2.109/pikachu/vul/sqli/sqli_str.php? name=xx%27+or+1%3D1%23&submit=%E6%9F%A5%E8%AF%A2 name=xx%27+or+1%3D1%23其实就是name=xx'or 1=1#进行了url编码之后的效果。
如果后台执行的sql语句为
$uname = $_GET('name')
select * from member where username='$uname';
再注入这样的语句时,由于'被转义了,得到的sql语句将是如下效果的
select * from member where username='xxx\'or 1=1#;,后面的引号被转义,导致不能和前面的 引号闭合上,那么这个sql语句的语法就是错误的,所有不会达到注入的效果,这就是防御的手段。
这样就没有办法了,不是的,还可以尝试宽字节注入,那么这里我们提一下,上面的语句其实应该是这样的
$uname = $_GET('name') -- $uname其实等于 xxx%27+or+1%3D1+%23,但是我们要解码啊,所以, 其实后台获得的这个$uname变量数据实际上是xxx0x27+or+10x3D1+0x23,因为%是url编码时十六进制数 据的前缀0x的简写。 后台转义单引号的时候,其实在前面加上\的时候,加的是\的十六进制编码,而\的十六进制编码为0x5C也就是说xxx0x27这个数据,其实到后台加上转义之后,是xxx0x5C0x27
那么发散思路,我们可能就会想到,由于汉字在GBK编码的时候是两个十六进制的字节,UTF8是三个字节,而 这个\是一个字节0x5c,如果我们能够再提供一个或者两个十六进制的字节数据和这个0x5c可以合并为一个汉 字的编码的话,那么这个\不就被我们吃掉了吗?那么单引号就又可以生效了。
2.3 注入测试
我们在进行宽字节注入的时候,得用到url编码的形式,所以我们就借助burp,或者在控制台直接写,但是这个请求是post,所以我们只能这么选了。
我们在前面随便加上%aa或者其他的,只要不是%27基本都可以,让他把后端的吃掉,变成一个数字,就好了!
xxx%aa%27+or+1%3D1+%23
所以PHP的网站一定要开启魔术符号的保护昂。而且注意,尽量不要用gbk编码的形式去连接mysql数据 库。如果非要使用不可,那么前面一定要做好编码数据的过滤。
三.偏移量注入
3.1 原理
偏移注入是一种注入姿势,可以根据一个较多字段的表对一个少字段的表进行偏移注入,一般是联合查 询,在页面有回显点的情况下。偏移注入现在用的不多了,因为有时候不太好用昂,示例中有提及。
在SQL注入的时候会遇到一些无法查询列名的问题,比如系统自带数据库的权限不够而无法访问系统自 带库。
当你猜到表名无法猜到字段名的情况下,我们可以使用偏移注入来查询那张表里面的数据。
3.2 举例
假设一个表有8个字段,admin表有3个字段。
联合查询payload:union select 1,2,3,4,5,6,7,8 from admin
在我们不知道admin有多少字段的情况下可以尝试payload:union select 1,2,3,4,5,6,7,admin.* from admin,此时页面出错
直到payload:union select 1,2,3,4,5,admin.* from admin时页面返回正常,说明admin表有三个字段
那么,如果页面上显示的2,3,4这三个字段数据,那么我们就可以将admin.*提前,比如 unionselect 1,admin.*,2,3,4,5 from admin ,那么admin表的数据在不知道字段名称的情况下就被回显 出来了。
3.3 测试
测试前我们先把代码给改一下
我们再提前检查一下两张表,member是七列,users是四列
union select users.*,1,2,3 from users#
刚好补三个,4+3=7,符号前面说的,刚好是把用户名给取出来了,因为他展示的问题,所以我们得不断地换users.*的位置来取出其他数据,但是因为他只取了username和email,所以有的时间我们还是取不到。
四.总结
本章节讲解了一下宽字节注入和偏移量注入,一个是仅限于gbk编码,一个是仅限于前库列数大于后库,网络安全课程会持续更新,期待大家的点赞关注加收藏。