感觉我能做出来的大家应该也都没问题,那就简单写写主要思路,后面的复现我会详细的去说
web
easyGooGooVVVY
简单了解一下反射机制与groovy表达式注入
payload
1 | return "".class |
RevengeGooGooVVVY
审了一下附件,自己重构的payload打不过去,后来发现第一题的payload也可以过关
1 | return "".class |
JavaSeri
看到cookie是rememberMe,就知道是shiro
用工具去一把梭了
Re
realme
附件丢给ChatGPT分析一下,自己再分析一下,应该是打热补丁和变种rc4
解决热补丁之后变种rc4模板直接套
1 |
|
Misc
NepBotEvent
稍微了解一下keylogger,然后知道应该是把键盘事件写入这个Linux内核文件里了
丢给ChatGPT分析即可
客服小美
用户名和木马地址都很好找,C2服务器很明显只有一条ip,ctftools工具箱一把梭了
后续要分析泄漏信息,把流量包交到CTF-NetA工具中,发现CS流量,上网找文章和脚本按步骤解密即可
一开始本来分离出了流量包中的stage文件,但是不知道为什么一直打不通
后面看到了这篇文章,想到题目既然给了,那应该要用进程内存解密
https://geekdaxue.co/read/jianouzuihuai@tools/cs_decrypt
SpeedMino
她高中的时候送我过一台小游戏机,只能玩俄罗斯方块的那种。今天重新见到俄罗斯方块,不禁怀念起那个时候。
或许是为了缅怀逝去的青春吧,我决定自己打到2600分,一次又一次的尝试,恍惚间我似乎忘记了flag的事情,似乎我只要一直打下去,就能回到那个夏天
当我回过神来,生活只剩下遍地狼藉,空落落的怀里,不见了那台小游戏机
(最后我是ce开倍速精灵开到100000倍速秒过的,青春过去的总是很快,暗自神伤时,总会想起那一句:往事总在回忆中被赋予意义;这张语文卷,似乎也是我青春的仓促谢幕吧)
最后想想讲讲自己的青春,或许也算得上是有趣吧
复现
(主要讲我自己的感受,学习的话还得看拉蒙特徐的博客)
safe_bank
这题我一直在蒸,虽然成功读到了源码,但是看到黑名单的那一刻我真的绝望了啊
- 测试
一眼就知道cookie有猫腻,改成admin发包之后发现只有假flag,查看了关于我们,应该是要打jsonpickle反序列化
稍微学习一些关于jsonpickle反序列化的知识,我贴两篇具体文章
https://xz.aliyun.com/news/16133
https://sugarp1g.github.io/2022/01/18/jsonpickle/
大概了解一下流程与操作
接下来看看注入点
我们的cookie解base64之后是
1 | {"py/object": "__main__.Session", "meta": {"user": "admin#", "ts": 1753669872}} |
时间戳这玩意纯假的,我随便贴都能过,说明后端是没什么校验的
那只能在admin处存在注入点了
- 读源码
按照文章中的payload一个个去尝试
https://xz.aliyun.com/news/16133
我基本上测了一圈,全部被ban,当时真的是要绝望了啊
(其实这里应该立马关注到py/object这条链子,因为cookie里就有object,普通的cookie可不会被过滤啊)
后面看到这两条,前面我已经测过os会被ban,于是就试了一下glob.glob这条链子
1 | {'py/object': 'glob.glob', 'py/newargs': {'/*'}} |
发现了这条链子没被过滤,但是也没有被执行
然后自己去改了一下,通过我贴的文章,大致可以了解到py/newargs和py/newargsex两者的区别(详细的可以看拉蒙特徐的博客)
那就把py/newargs改成py/newargsex
然后发现不起作用,我之前有过这方面的经验,感觉上应该是单引号和双引号的问题,于是把单引号改为双引号
OK这下是过了,但是报错了(但这起码说明了我们引号是改对了)
(以下是错误的payload)
1 | {"py/object": "__main__.Session", "meta": {"user": {"py/object": "glob.glob", "py/newargsex": {'/*'}}, "ts": 1753669872}} |
深入的去学习了一下newargs和newargsex之间的差别,再问了一下ChatGPT,应该是py/newargsex对应的参数结构不对,我就让AI生成了一个,最后结合我们之前已经测出来的部分黑名单,写出正确的payload
1 | { |
成功读取
注意到/readflag
1 | {'py/object': 'linecache.getlines', 'py/newargs': ['/flag']} |
就用这条payload来读文件
按照上面列目录的方法来改这条payload
发现成功读取,那么我们把源码交给AI整理一下
1 | from flask import Flask, request, make_response, render_template, redirect, url_for |
注意看黑名单
1 | FORBIDDEN = [ |
笑死我了根本打不动一点,我学到的链子基本上都要靠这其中的两种到三种方法,而且
1 | payload = json.dumps(data, ensure_ascii=False) |
unicode编码绕过也行不通
然后我这题就没做出来
赛后问拉蒙特徐,他的大胆想法直接给我惊呆了
他直接用list.clear()的方法把黑名单给扬了(我哩个大豆)
1 | {"py/object": "__main__.Session", "meta": {"user": {"py/object":"__main__.FORBIDDEN.clear","py/newargs": []},"ts":1753446254}} |
在他的博客中也详细的讲到了如何去验证这个poc,我这里就不多说了,大家可以去看他的博客,就在我的友链最上方(真的是恩师啊)
黑名单扬了之后大家就都会做了,这里就不多赘述(主要是这个想法太大胆,我之前从来没有想到过)
补档之预期解
现在是7月18号晚上8点29,群里大家都在聊safe_bank,把黑名单扬了的做法官方说是非预期,然后就有预期解大佬出来现身说法
注意到源码util.py下的某函数
1 | def translate_module_name(module: str) -> str: |
此处为了兼容python2,把exception当成builtins了
再看一下我们上面的黑名单
1 | FORBIDDEN = [ |
exception并不在内,那直接构造链子打就行了!!!
(一定要培养强大的代审能力)
那payload手搓都可以了,原理就是exception.eval=builtins.eval
1 | {"py/object": "__main__.Session", "meta": {"user": {"py/object":"exceptions.exec","py/newargsex": ["???"]},"ts":1753706694}} |
问号那个地方我一直写不明白,因为我感觉我总是得用到os等关键字,然后去问了下lmtx
666又学到新东西了,好开心