Lodash + ejs RCE

环境配置

版本信息

{
  "dependencies": {
    "ejs": "^2.7.4",
    "express": "^4.18.2",
    "lodash": "^4.17.4"
  }
}

server.js

var express = require('express');
var _= require('lodash');
var ejs = require('ejs');
const bodyParser = require('body-parser');

var app = express();

app.set('views', __dirname);

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

app.post('/', function (req, res) {
    console.log(req.body);
    _.merge({}, req.body);
    res.render ("./test.ejs",{
        message: 1
    });
});

app.listen(8081, function () {});

开始调试

我们先来看看在res.render的时候到底发生了什么

2023-03-12T03:45:14.png

继续跟进

2023-03-12T03:45:21.png

继续跟进

2023-03-12T03:45:27.png

继续跟进

2023-03-12T03:45:35.png

继续跟进

2023-03-12T03:45:42.png

继续跟进

2023-03-12T03:46:05.png

继续跟进

2023-03-12T03:46:15.png

继续跟进

2023-03-12T03:48:01.png

继续跟进

2023-03-12T03:48:09.png

继续跟进,发现opts.outputFunctionName没有过滤,可以造成代码注入

2023-03-12T03:48:15.png

配合Lodash的原型链污染,可以RCE

2023-03-12T03:48:22.png