你驻足于春色中,于那独一无二的春色之中.
本来说专心搞毕业论文的,还是忍不住做了几天。Writeup 基本漫天飞了,这里主要记录脑洞过程以及~~按照官方的要求,过几天到时间了再发。
_(:з」∠)_
总体感受,Web 比较中规中矩(除了翻人家博客那个,不看评论可能就 get 不到这个脑洞);逆向和 PWN 跟着网上别人的思路走了一遍,权当学习;杂项的密钥分发和声纹倒是之前少见的点。
解密 URL 里的字符发现是两次 base64+hex,发现是图片名 flag.jpg。猜测可能是文件读取。构造 index.php 的编码字符串 TmprMlpUWTBOalUzT0RKbE56QTJPRGN3。读取到的源码有两个点。
一个点是别人的博客,访问后在大家的评论中知道是另一篇博客,然后卡在这里一天,第二天随手试了一下博客里的文件名,发现了 flag 的文件名 “f1ag!ddctf.php”
第二个点是 config 的过滤,一开始还以为是要绕这个规则,后来发现不是,直接利用过滤去读第一个点的 flag 文件就行了。
对于页面很干净的网页,要么上手扫文件,要么抓包看回复,要么看 JS。
index.js 中发现另一个接口,伪造 http 头访问
1 | didictf_username: admin |
发现源码文件,看到几个敏感词知道是反序列化,利用反序列化的点需要伪造 cookie,伪造 cookie 需要知道 key。
1 | if(!empty($_POST["nickname"])) { |
这段代码可以看出,利用 nickname=%s 可以带出加密 key,这个点也是前一天访问怎么都没反应,第二天就好了。
有了 key 之后,生成序列化的 Applicaiton 类并且给 path 赋值,这里需要简单绕一下过滤规则,根据提示
1 | ../config/flag.txt 正好 18 位 |
上传图片中带有 phpinfo() 即可得到flag。
反复构造上传无用后,发现了图片中的关键字,说明做了二次渲染。搜了相关脚本,使用后无效。分析应该和图片的选取以及放的位置有很大关系。
感觉图片越大可能二次渲染后没有更改的地方就越多,所以用 compared 工具反复比对同一张上传的图片和上传后二次渲染的图片之间的相同点,在相同点反复插入字符串,最后绕过二次渲染拿到 flag。
关键代码在于请求参数的分割和执行
1 | event_handler = eval(action + ('_handler' if is_action else '_function')) |
结合上面的 eval 可以通过注释符来执行函数,直接获取 flag 的函数被 ban 掉了,但是 get_flag 会把 flag 放入 session 中,再利用 p牛的解密脚本即可得到 session 的内容。
1 | /?action:trigger_event%23;action:buy;3%23action:get_flag;%23action:buy;5%23action:view;index%23action:get_flag; |
就差一步~~
先是根据提示做 xss,既然不是 cookie,那就 xss 一下页面,在返回的页面中发现了一个接口,
1 | 已经不记得接口叫什么.php?id=1 |
再根据第二个提示去注入,忘记尝试宽字节注入了,而且又因为 xss 到了另一个 hint.php,所以思路就被带偏了,最后发现其实对这里做宽字节注入就可以了。
买票,票价可控,但是无法小于100,不过可以修改为 1000 还是有点迷。猜测是溢出,一开始一直在试 int64,int32 都没有结果,最后发现是 uint32,只要令
1 | 100-4294967394=-4294967294 溢出就行 |
进入后,发现需要输入 id 和 ticket 来淘汰其他人,发现不同账号得到的 ticket 可以通用,于是分析整个获取 ticket 的过程,写脚本批量注册账号,获取 ticket,再淘汰别人。
值得一提的是,id 会大于 100,也就是说和你一起吃鸡的 ticket 是在一个大于 100 的数据空间中的,因此即使你已经有了 100 个不同的 ticket,也不能淘汰掉所有人~~~,跑脚本的时候开的是三进程,跑了很久才跑出 flag。
这道题倒是帮我复现了一下之前 mysql 的漏洞,看到有对方来扫自己,猜到了应该是之前看过的 mysql 攻击反制,可以反读攻击者的文件。
网上找了相关的蜜罐脚本,运行之后发现题目的 agent 需要返回带有 mysqld 字样的字符串,简单构造一下。读取文件基本上按照以下顺序进行:
1 | /etc/passwd,验证漏洞 |
思索了一下,没有直接执行命令的思路,发现开了 22 端口,想去获取用户私钥发现失败了,然后就想直接读数据库文件,发现我用的脚本竟然都不全文件,因此对蜜罐程序做了一些修改,最终在
1 | /var/lib/mysql/security/flag.ibd |
文件中读到了 flag。
又是干净的页面,读取 cookie 进行解密,发现了 padoraclexxxxx 等字样,推测是 padding oracle 攻击,另外还可以看见一个验证 cookie 的 api,可以得到一个验证明文
1 | {'id':'100','is_admin':false} |
估计是伪造这一段信息,另外发现还有一个读文件的 api,可以读 1.txt
线索就到这里,时间原因,没有继续肝这道题。
跟着网上大佬的操作走了一波,脱壳,上 ida 和 od,分析密码表和偏移,最后写程序做解密。
分析流量,得到三张图片,知道访问了一个在线图像加密网站和图床网站。
一开始,以为要对比两张一样的图来分析,后来想到第三张图片不是个钥匙,于是在源码发现原图是 1600x800 大小的,于是修改 png 的大小就可以看见密钥了,再通过在线网站解密图片就可以直接得到 flag。
根据提示,估计密钥分配是先分成两个子密钥,门限为 2,每个子密钥再分成门限为3的子子密钥。
一开始没有想通 p 大素数的作用,因为网上找到的程序都是随机生成大素数,因此用这些程序只用提供子密钥。后来,对网上的一个 python 库做了点修改,定死了大素数,按照先解出两个组织的子密钥,再解出总密钥的流程即可得到 16 进制编码的 flag。
算是把理论课学的知识用到了实际上。
其他的题目,安卓和逆向不会,北京地铁和 MulTzor 乍一看没有思路就没继续做了,声纹锁觉得有点意思,但是也没有 get 到什么明确的突破点。
总的来说,这次的题目和去年一样,做起来还是有意思的,而且感觉今年参加的人明显要多很多。