又来水文章了
十几天前的比赛,今天没blog写,来复现下web签到题。
clone官方wp&docker环境
docker build -t sctf/clouddisk .
docker run -d -p 8090:3333 2f2
- 使用当前目录的dockerfile提取镜像,tag叫做sctf/clouddisk
- 后台创建新容器并制定映射端口为8090
+上题目给的一段源码:
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const Koa = require('koa');
const Router = require('koa-router');
const koaBody = require('koa-body');
const send = require('koa-send');
const app = new Koa();
const router = new Router();
const SECRET = xx
app.use(koaBody({
multipart: true,
formidable: {
maxFileSize: 2000 * 1024 * 1024
}
}));
router.post('/uploadfile', async (ctx, next) => {
const file = ctx.request.body.files.file;
if (!fs.existsSync(file.path)) {
return ctx.body = "Error";
}
if(file.path.toString().search("/dev/fd") != -1){
file.path="/dev/null"
}
const reader = fs.createReadStream(file.path);
let fileId = crypto.createHash('md5').update(file.name + Date.now() + SECRET).digest("hex");
let filePath = path.join(__dirname, 'upload/') + fileId
const upStream = fs.createWriteStream(filePath);
reader.pipe(upStream)
return ctx.body = "Upload success ~, your fileId is here:" + fileId;
});
router.get('/downloadfile/:fileId', async (ctx, next) => {
let fileId = ctx.params.fileId;
ctx.attachment(fileId);
try {
await send(ctx, fileId, { root: __dirname + '/upload' });
}catch(e){
return ctx.body = "SCTF{no_such_file_~}"
}
});
router.get('/', async (ctx, next) => {
ctx.response.type = 'html';
ctx.response.body = fs.createReadStream('index.html');
});
app.use(router.routes());
app.listen(3333, () => {
console.log('This server is running at port 3333.')
})
当时做的时候通过万能的google搜到了这样一个issue:
https://github.com/dlau/koa-body/issues/75
然后直接exp打出的flag。现在来康康。
emmm~
虚拟机的node环境搞了一个多小时没搞好,现在都1:24了,狗命要紧。就不深入了。
在issues中写的已经很明白了:
Suppose you have JSON body parsing enabled on a POST or PUT route, say ‘/upload-files’, as well as multipart parsing. This is quite easy to do e.g. if you add JSON parsing as global middleware. Suppose it expects the files to be in a field named ‘uploads’. Then you can make a POST or PUT request to ‘/upload-files’ with a JSON body that looks something like {“files”: {“uploads”: [{“path”: “/any/file/path”}]}}, making the request handler think a file has been uploaded to /any/file/path. Now suppose that the handler is set up to copy uploaded files into a public uploads folder. By choosing the path appropriately I can make the server copy any file I like on the server into the public uploads folder and then view its contents. So by using well-known paths of sensitive files I can read private keys, passwords etc. and maybe even gain full access to the server this way.
大概意思就是说如果向文件上传的路由如:/uplaod上传json主体的格式,那么其中path将被解析成已经上传完的文件位置保存到相应文件中。
poc:{"files":{"file":{"name":"xiaoyue","path":"/etc/passwd"}}}
这样直接catflag也就行了。
{"files":{"file":{"name":"xiaoyue","path":"flag"}}}
emm~
poc&exp收集学习
fabric单机部署