对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
导致恶意代码被执行