sqli-labs之宽字节注入

在开始之前我先理一下几种编码,因为我发现我有点混淆,对它们的概念模模糊糊的样子。

URL编码:浏览器从表单中获取所有name和value,将name,value参数编码,去掉那些不能传送的字符,作为URL的一部分发给服务器。
URL编码规则:每一对name/value之间用&分隔,name和value之间用=分隔,特殊符号用" % + 该字符ascll码的十六进制 "表示,比如“\”,它的ascii码是92,92的十六进制是5c,所以“\”的url编码就是%5c。

GBK编码:汉字内码扩展规范,GBK采用单双字节变长编码,英文使用单字节编码,完全兼容ASCII字符编码,中文部分采用双字节编码。GBK 规范收录了 ISO 10646.1 中的全部 CJK 汉字和符号,并有所补充。

一、宽字节原理:

在我们注入的时候,注入的单引号,双引号,反斜杠等字符可能会被过滤掉,如使用addstring函数转义,或者使用正则表示过滤,单引号 ’ 被转换为 \ ’ ;因此我们要想办法把前面的反斜杠消灭掉。

MYSQL在使用GBK编码时,会认为两个字符为一个汉字,即双字节编码。如:%aa%5c为一个汉字 “猏”,%df%5c为汉字“運”。但是,前一个字符的ascll码必须大于128才能达到汉字的范围。
反斜杠编码为%5c,单引号为%27,所以在注入时单引号被转义后,urlencode( \ ’ )=%5c%27,我们在它前面加%aa变成%aa%5c%27,GBK编码时会把%aa%5c编码成汉字,而%27就落单了,成功把反斜杠消灭掉了。

addslashes(string)函数:返回 在预定义字符前添加了反斜杠的 字符串。
string:要转义的字符串;
预定义字符:单引号’ 、双引号’’、反斜杠\ 、NULL;
在这里插入图片描述
在这里插入图片描述
此外,还有一种方法,如果反斜杠没有被过滤的话,在单引号前面加上一个反斜杠,就成了%5c%5c%27,把后面那个反斜杠转义掉了。

Less-32

sqli-labs之宽字节注入_第1张图片
正则表达式函数preg_replace(pattern,replacement,string):
pattern:目标字符串中要被替换的字符串;
replacement:替换成的字符串;
string:目标字符串;
搜索string中匹配pattern的部分, 以replacement进行替换。

源代码的意思为:
把反斜杠 \ 转换成 \ ;
把字符串中的单引号 ’ 转换成 ’ ;
把双引号转换成 " ;

当我输入id=1‘ 时,它是个显注,但是,单引号已经被转换成了’sqli-labs之宽字节注入_第2张图片
所以我们要用宽字节注入,在单引号前加上%aa,成功把单引号隔离!!出现了语法错误的报错
sqli-labs之宽字节注入_第3张图片
问题来了,上面看到网页显示的是一个菱形的乱码,可是它确实已经被数据库jbk编码了,如下图源码,每执行一次查询设置一次gbk编码:
sqli-labs之宽字节注入_第4张图片
而网页上的乱码只是浏览器的文字编码设置问题,我们需要在浏览器的“文字编码”插件里设置成“简体中文”,j就可以显示汉字啦!
sqli-labs之宽字节注入_第5张图片
看结果,1的ascll码十六进制为31,df5c对应汉字,27对应单引号
sqli-labs之宽字节注入_第6张图片
尝试注入,成功注出数据:
sqli-labs之宽字节注入_第7张图片
只要把反斜杠消灭掉,接下来就跟普通显注操作一样啦,可以用union联合查询注入。

Less-33

sqli-labs之宽字节注入_第8张图片
它用了addslashes函数,同less32一样,把单引号,双引号,反斜杠过滤掉了。
可以用和less32一样的payload,宽字节注入。

less-34

这里是个POST型宽字节注入,其实和GET型宽字节注入的区别就是不会进行URL编码。因为是以表单的形式提交数据,不会进行url编码,所以我们要输入ascll码大于128的字符,怎么获得呢?可以把%aa进行url解码,把得到的字符复制进去

username: 2�’ or 1=1#
password: 随便输

sqli-labs之宽字节注入_第9张图片
成功注入。
下面看源代码:sqli-labs之宽字节注入_第10张图片
第一点,它用adslashes函数进行了过滤;
第二点,看它的SQL语句,将数据带进去后完整的语句就是这样

SELECT username, password FROM users WHERE username='2�\' or 1=1#' and password='' LIMIT 0,1

where子句中因为1=1永远为真,所以能查出所有数据。因为一次只能显示一组数据,把username改为:2�’ or 1=1 limit 1,1# 就能查出第二组数据。
sqli-labs之宽字节注入_第11张图片

less-35

看源代码:
sqli-labs之宽字节注入_第12张图片
虽然它对输入的id用函数进行了转义,但是在它的SQL语句中id并没有用引号包裹,它就是个数字型注入,所以我们就不用输入单引号了,也就不用考虑addslashes函数的事。
sqli-labs之宽字节注入_第13张图片

less-36

直接看原码,sqli-labs之宽字节注入_第14张图片
它用的 mysql_real_escape_string()函数进行转义。
sqli-labs之宽字节注入_第15张图片sqli-labs之宽字节注入_第16张图片
其中,\x00表示十六进制数00的意思。
sqli-labs之宽字节注入_第17张图片
\x表示后面的字符是十六进制数,\0表示后面的字符是八进制数。例如十进制的17用十六进制表示就是‘\x11’,用八进制表示就是‘\021’;

注入原理同less-33.

总之,用来转义的函数一般为 replace,addslashes,mysql_real_escape_string这三种,都是使用宽字节注入;按请求方式分为GET和POST,区别在于GET会进行URL编码,而POST不会;按注入类型分为字符型注入和数字型注入,数字型注入就不用考虑转义函数了。

二、防御
1.使用utf-8编码
2.使用mysql_set_charset(‘gbk’,$conn)设定字符集,然后用mysql_real_escape_string转义,mysql_real_escape_string与addslashes的不同之处在于其会考虑当前设置的字符集。
3.设置参数,character_set_client=binary

你可能感兴趣的:(#,SQL注入学习笔记)