简单记录下第二次参加CTF。。虽然还是做不出来题。。。
这篇文章主要就是想分享下 Mysql if 的一个小技巧。增加一个布尔注入的小姿势。
Web - realezjvav
本来看到 java 没打算看的,可是出题人说这个并没有考到多少 java 知识。便去瞄了下。此题需要两步才能得解。我只做出了第一步。。。第一步是 SQL布尔注入,第二步虽然没做出来,但是估计是 fastjson 的 RCE

通过测试得知,password
存在 SQL 注入
1 | [PAYLOAD:] |
在经过一番尝试,发现当字段中存在 union
或者 sleep
时,会将整个 password
的值清空再带入到 SQL语句中。
1 | [PAYLOAD:] |
并且值得注意的是,不管万能密码是否奏效, and 和 or 怎么混着用,页面返回都是一样的,我们只能根据状态码来判断 SQL语句是否生效。
这里有两种思路:
无回显的 SQL 注入,那么我们可以使用 DNSLOG 来创造回显。可惜这里的 load_file() 没法正常使用。 load_file() 无法制造 DNSLOG 的原因一般为两个l:
Linux环境
或secure_filr_priv=NULL
既然需要根据状态码来判断SQL语句执行状态,我们就得设法让 SQL 语句报错。这里就涉及到一个 Mysql
if
的小技巧
在 Mysql 中,if
的基本用法如下:
1 | if(表达式, 表达式为True执行的语句, 表达式为False执行的语句); |
简单使用:
1 | select if((select 1) ,1 , 0); |
值得注意的是,当表达式返回 True 时,是不会执行 if
的第三个参数的。同理,当表达式返回 False 时,也不会执行 if
的第二个参数。
并且 if 的参数只接受一行值,如果执行的子查询返回了多行值,将会报错。
综上所述,我们可以构造这样的 POC
1 | select if( (select 1), 1, (select 1 from mysql.user) ); |
明白这种性质之后,我们就可以使用这个性质来进行基于 HTTP code 的布尔盲注了
Poc:
1 | [PAYLOAD:] |
结合 substr() 和 limit 注表名:
注意:如果想扔到 burp 里跑十六进制的表名。注意十六进制是 0-9,a-f 而不是单单的 0-9。我这里就被坑了一下。。。
1 | [PAYLOAD:] |
最后爆出密码登陆后台,发现里面的功能传输格式是 json 格式,猜测可能是 fastjson的漏洞。可惜没怎么了解,遂没有继续下去。
Web - Ez_game
一开就是个游戏,提示通关有 FLAG

瞄了一下网络请求,没有与后端交互的请求。估计都是 js 写的。
查看首页HTML源码,发现注释写着一共有十关
找到一个 js 文件 game.js 。里面似乎都是些人物的属性。
1 | class PlayerData |
尝试直接在 console 控制台处修改人物属性。发现了一个 player 对象
1 | Player |
尝试修改这些属性

发现我们变强力了。
玩一玩这个游戏,玩到第三关的时候,发现死亡后重生时可以进入之前存档的一关。
在 js 中找到疑似 存档关卡的一个值 localStorage.kbap_warp
1 | function NextLevel() |
我们先径直来到第三关,然后设置 localStorage.kbap_warp
为 10,这样我们死亡后去进入存档,就可以直接打 boss 战了。
来到 boss 战把自己的属性修改强力,很轻松就斩杀 Boss