NSSCTF Round#8 web
最后一题想到一个非预期,嗯~~~非预期没做出来
MyDoor
任意文件包含 php://filter/read=convert.base64-encode/resource=index.php
然后传参 N[S.S=system("ls");&file=
弹 shell,然后找到 藏 flag 的地方
MyPage
和 MyDoor 差不多,这里使用脏数据绕过
1 | php://filter/read=convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/cwd/index.php |
然后读取 flag.php 嘛
Upload_gogoggo
传一个文件,而且会执行文件名,上传 run.go 的话,会执行 go run run.go
······
写一个弹 shell 的 go,命名为 run.go 传上去就好了
1 | package main |
然后 flag 在 /home/galf ······ 好无语啊
ez_node
这一次比赛的时候,在没看到 hint 之前,想到了一种方法······到最后一步,已经可以把 flag 从根目录移动到 /app/ 目录下了,可还是读取不了
之后看到 hint,才知道另一种做法:只需要 原型链污染,和一个 require(‘./err.js’) 并且 目录里面没有 package.json 文件
参考: https://ctf.zeyu2001.com/2022/balsnctf-2022/2linenodejs (这不是和原题一模一样嘛)
保险起见,利用一下文件上传功能,上传 preinstall.js 到 ./upload/bcb0b237d4d7554e36ae7984cc6f28b3.js
然后打 payload 就行
1 | { |
一开始在本地测试能不能弹计算器,一直没成功。
后面才发现,一开始为了方便,自己给项目加了 package.json,删掉它就好了
再说说我本来的做法
原型链污染,是大家都可以做到的,我想到污染后对 req.files[0]
这一参数可控,那么 oldName 和 newName 将不受约束,可以将 flag 移动到 public 目录(美好的想象)
实际上确实如此,发送一个简单的不上传文件的 POST 请求,就能使 req.files[0].path
获取到原型中的值
1 | let oldName = req.files[0].path; |
开始来实践一下,发送如下 payload
1 | { |
成功的将任意一个文件重命名,修改其后缀名,问题是,还无法跨目录移动文件
经过查找资料,发现 fs.renameSync
可以接受 oldName=URL object
,而此时的 newName=oldName+path.parse("xxx").ext
不会报错,而是 Object to String
转换成 newName="[object Object]"+path.parse("xxx").ext
本地开启环境,测试一下:
向 /pollution 发送
1 | { |
POST 直接访问 /upload 路由
进入容器中查看,发现成功的将 flag 移动到 /app 目录中,命名为 [object Object].xxx
要是能移动到 public 目录里,那这题的非预期就完成了,可惜不知道怎么继续弄