前言
这几关主要练习waf与单引号过滤的绕过,其中29-31关需要配置好tomcat并开启服务,接下来开始解题
ps.整理了关于sqli-labs靶场的博客,将分散的几篇整合了起来。
less29-31
三关一起写,因为除了字符型注入类型不同,其他方面几乎都是一致的。我们先看源代码:
1 | $qs = $_SERVER['QUERY_STRING']; |
源码中出现了$_SERVER函数,关于这个函数的具体用法可以参考本段最后的链接。中括号中的元素为’QUERY_STRING’,意思是查询字符串,如果有的话通过它进行页面访问。而我们发现这关还有一个login.php文件,这就意味着这关其实是两个服务器在进行作用。
PHP手册:$_SERVER函数
那么我们来看看login.php:
1 | function whitelist($input) |
这两个自定义函数可以说是这个php文件中的重中之重,先介绍下其中的explode()与foreach()。
explode()把字符串打散为数组,例如$str=”Hello World”在explode(“ “;$str)函数作用下就被打散成了Array([0] => Hello [1] => World)
而foreach()函数主要作用就是遍历数组,将数组被分割的数组一一输出出来。这个函数有两种语法:
- foreach (array_expression as $value):每次循环中,当前单元的值被赋给 $value 并且数组内部的指针向前移一步
- foreach (array_expression as $key => $value):同语句一,同时当前单元的键名在每次循环中赋值给$key
这两个自定义函数的效果就是将语句从“&”中分割开,然后再分割开的数组的前两位找id值,如果找到了就截取这个数组的第4位到30位的长度交给preg_match()进行正则匹配。
这种过滤就和相当于一个waf了,是相当强的过滤。但是结合源码我们发现,tomcat获取的是第一个数据,而处理我们想要数据的apache获取的是第二个数据。因此这题的思路就是构建payload让tomcat取得第一个数据,而我们的注入的语句从第二个语句中注入:?id=1&id=0'union select 1,database(),3 --+
这样这题就解出来了,接下来就是老流程了。
less-30双引号注入,less-31双引号加括号注入,语句构建思路与29关完全一致。
less32-33&36
直奔32关,老规矩上源码:
1 | function check_addslashes($string) |
第一句的作用是搜索id中的单引号与反斜杠并用斜杠进行替代,后面两句的作用是为了防止你对反斜杠进行注释。
这里也介绍一下preg_quote()函数,这个函数的功能为向其中每个正则表达式语法中的字符前增加一个反斜线,正则表达式特殊字符如下:. \ + * ? [ ^ ] $ ( ) { } = ! < > | : -
接着是这句代码:mysql_query("SET NAMES gbk");
通过这句语句程序对对$con1进行gbk编码,关于编码的内容在我的上一篇博客进行了介绍,可供参考:
学习解析Unicode与gbk编码
我们知道gbk编码中英文及符号等都是两个字符,因此我们构建payload时可以使用%aa或者%df将反斜杠给吞掉。这里分析原理:
'URL编码为%5c%27,在前面加上一个%aa,就构成了%aa%5c%27,在进行gbk编码后将两个字节当成了一个汉字,此时%27就被独立了出来,因此单引号就被成功注入进去了。
了解了原理,我们就能进行payload构建了:?id=-1%df'union select 1,database(),3 --+
最后愉快爆库,不过要注意,由于单引号被过滤,因此在爆表等操作时记得将’security’进行十六进制编码来绕过过滤。
less-33与32关的区别在于这关使用了addslashes()函数进行过滤操作,而上关是preg_quote(),构建payload思路与32关一致。而less-36则是使用了mysql_real_escape_string()进行过滤,本质上都没什么差别。
less-34&37
这两关解法一致一起写了。这关是POST注入,burp suite直接拉出来用。有人会问为什么不用hackbar呢,我们来分析一下:
首先这题依然是宽字符注入,因此我们构建payload:uname=admin%a0'union select 1,database(),#&passwd=1&submit=Submit
我们发现登录失败了,这是怎么回事呢,我们抓包来看看:uname=admin%25a0%27union+select+1%2Cdatabase%28%29%2C+%23&passwd=1&submit=Submit
admin与a0之间多出了一个%25,这是因为在POST上传数据时,原来%a0前的那个“%”被URL编码成%25,因此我们只需要将这个25删掉就行了,当然在Requset中直接进行注入也是可以的:
同样记得在爆表等操作时记得编码,同32关一样,盲注和报错注入同样可以操作。
这里还有一个方法,�法,直接上效果:
而37关区别只是使用了mysql_real_escape_string()函数进行过滤。
less-35
这关最有意思,转义了引号,结果源码的查询语句没加引号:$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
那这题就不是字符型注入了,而是数值型注入,因此我们直接构建payload,记得编码绕过过滤。这道题只能说回归初心了。