CTF之懵懂时期系列---因缺思汀的绕过
题目链接:http://ctf5.shiyanbar.com/web/pcat/index.php
这道题严格来说,我只解了一半,考点在于源码分析、group by with rollup、关键字绕过.
这一篇的文章和之前ctf系列的不一样,之前的都是学习,反推别人的思路,这次以自己的思路为博客的主线。
一、发现源码
右键查看网页源代码(ctf是否有意培养我们这样的习惯?)
source.txt这个字段有些诡异,测试一下看看:
http://ctf5.shiyanbar.com/web/pcat/source.txt
结果很明显,源代码在这里。
二、代码审计
我们审计下代码,发现了这些关键信息。
- AttackFilter这个函数过滤了and|select|from|where|union|join|sleep|benchmark|,|(|)等关键词和符号。
- 注入点如下SQL
SELECT * FROM interest WHERE uname = '{$_POST['uname']}'
- 三种不同的error print,可以让我们基于错误信息判断注入情况
- 针对返回结果数(1)和pwd进行校验,确认登入信息。
三、构造sql的探索过程
可知,注入点的语句是它:
SELECT * FROM interest WHERE uname = '{$_POST['uname']}'
条件反射想到,闭合加注释注入。
注入语句: ’ or ‘1’=‘1’ #
前面一个单引号用于闭合代码前面的单引号,#注释掉代码后面的单引号。于是构造了这样的sql
SELECT * FROM interest WHERE uname = '' or '1' = '1' #
返回错误如下,复查代码发现,此条sql语句返回的结果有多个,> 1。
那怎么办?使用limit限制结果呢?
注入语句:’ or ‘1’ = ‘1’ limit 1 #
SQL语句就变成了:
SELECT * FROM interest WHERE uname = '' or '1' = '1' limit 1 #
输入,结果:
很好,基于不同的错误,确认了注入点可不断地利用,也可用于验证我们的思路。(感谢《SQL注入与防御》一书,让我逐渐对注入和渗透有了科学验证的思路过程,思路很重要)
回头想下,我们要构造的SQL语句要达成什么样的目的呢?
根据代码,我们要构造可以返回有且只有一个结果,并且pwd和post(我们填入的密码)中pwd一致。
首先,返回一条结果我们已经做到了,接下来就是要知道pwd是什么。当然该网站inerest数据我自然是没办法知道的。所以,我填入的密码(pwd)自然也就是null,而该SQL构造的核心,就是要构造一条:只返回一条结果,并且pwd为null的SQL语句。
好了,上述就是我所能做到的推断了。
四、关键词绕过
可知,题目过滤了union select where等关键字,我们在注入的时候大部分情况下都要用到这些关键字,那怎么办呢?我们可以用其他关键字绕过关键字过滤
如果or 、and 被过滤,可以用||、&&代替,如果select被过滤,可以用group by配合完成查询的目的。
网上有很多类似的资料,属于死知识,不用硬记,不是很重要,用熟就好。但是这里有个问题,我怎么知道自己成功绕过了关键词的封锁了呢?
还是这个思路:基于错误判断,我输入select,返回:
而输入
’ or 1 group by pwd limit 1 #(密码不对错误)
’ or group by pwd limit 1 #(多个结果错误)
可以通过group by也可以同样达到union select limit 1的作用。
注意:第2和第3个返回的结果不同,目前只是猜测(有空在电脑上下载mysql实验下)。or 前后都是false的情况下,直接返回了错误的信息,而or 后面直接跟上1~9数字,是代表true的情况,而后面的语句会继续执行
五、**,拿到flag!
这里,我是没有想到,新接触到的方法。
使用group by with rollup语句分组查询。
为什么要使用with rollup,主要原因是with rollup分组更加详尽,最后一组可能会出现null,从而满足我们前面SQL构造的目标。配合offset逐渐进行尝试。
这里有关于SQL语句的知识点不做过多描述,可自行百度,主要是注入思路。
poc:
‘ or 1 group by pwd with rollup limit 1 offset 2 #
flag到手!
六、思路优化
一道题目下来,发现做题时的思路有些繁琐没有系统的,可以进一步优化。
在实际渗透时,我在代码审计上是走了弯路的,其原因在于:没有充分认识到注入点的真实意图。说白了,审题不够。
我在没有丝毫思路的情况下,使用了
' or '1'='1' #
而为错误的结果而纠结,浪费了相当一部分时间。
其次,没有充分认识到不同错误,代表着不同的原因,也浪费了一部分时间。
而如果这两者我都考虑到了,就可以大大提高思维的效率,总结如下:
1、了解注入点成功的关键是什么,提炼出条件
2、基于错误,要知道不同错误代表什么含义。
就这样,在高铁上完成了这篇文章,继续努力吧。