[GKCTF2020]EZ三剑客-EzNode(settime溢出+沙盒逃逸)

Posted on 2020-05-25,3 min read

对nodejs还是不太熟。。

const express = require('express');
const bodyParser = require('body-parser');

const saferEval = require('safer-eval'); // 2019.7/WORKER1 找到一个很棒的库

const fs = require('fs');

const app = express();


app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// 2020.1/WORKER2 老板说为了后期方便优化
app.use((req, res, next) => {
  if (req.path === '/eval') {
    let delay = 60 * 1000;
    console.log(delay);
    if (Number.isInteger(parseInt(req.query.delay))) {
      delay = Math.max(delay, parseInt(req.query.delay));
    }
    const t = setTimeout(() => next(), delay);
    // 2020.1/WORKER3 老板说让我优化一下速度,我就直接这样写了,其他人写了啥关我p事
    setTimeout(() => {
      clearTimeout(t);
      console.log('timeout');
      try {
        res.send('Timeout!');
      } catch (e) {

      }
    }, 1000);
  } else {
    next();
  }
});

app.post('/eval', function (req, res) {
  let response = '';
  if (req.body.e) {
    try {
      response = saferEval(req.body.e);
    } catch (e) {
      response = 'Wrong Wrong Wrong!!!!';
    }
  }
  res.send(String(response));
});

这边导入了一个safer-eval
nodejs大多数都是库的问题。估计就是沙盒逃逸
找到https://github.com/commenthol/safer-eval/issues/10
看下怎么传值
先进入了app.use
然后请求的路径如果是/eval

app.use((req, res, next) => {
  if (req.path === '/eval') {
    #如果请求路径是/eval就执行下面的
    let delay = 60 * 1000;
    #定义了一个delay
    console.log(delay);
    if (Number.isInteger(parseInt(req.query.delay))) {
        #parseint返回一个整数。然后判断是否是一个整数。
      delay = Math.max(delay, parseInt(req.query.delay));
      #如果传入是整数。就和原先定义的delay取最大值给delay
    }
    const t = setTimeout(() => next(), delay);
    设置超时。如果超时。就进入下一个路由。也就是eval。执行恶意代码
    setTimeout(() => {
      clearTimeout(t);
      console.log('timeout');
      try {
        res.send('Timeout!');
      } catch (e) {

      }
    }, 1000);
    #超时1秒就执行timeout。
  } else {
    next();
  }
});

这里的意思就是。我们传入一个delay和原先定义的60000进行比较。大的值复制给delay
然后作为timeout的值传入
显然。默认定义超时6秒。进入下个路由。
但是我们的代码不能超时6秒。也就不能进去下个路由执行沙盒逃逸了
那么问题就出在这个settimeout函数上。

delay传入4294967296。造成settimeout设置为1.
如果超过1毫秒。就进入eval
导致恶意代码被执行

下一篇: GKCTF WP→