[SCTF2020]CloudDisk

又来水文章了
十几天前的比赛,今天没blog写,来复现下web签到题。


clone官方wp&docker环境

docker build -t sctf/clouddisk .
docker run -d -p 8090:3333 2f2
  1. 使用当前目录的dockerfile提取镜像,tag叫做sctf/clouddisk
  2. 后台创建新容器并制定映射端口为8090

[SCTF2020]CloudDisk_第1张图片

+上题目给的一段源码:

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"}}}

[SCTF2020]CloudDisk_第2张图片

这样直接catflag也就行了。

{"files":{"file":{"name":"xiaoyue","path":"flag"}}}

emm~

poc&exp收集学习
fabric单机部署

你可能感兴趣的:(CTF)