javascript.express.security.audit.res-render-injection.res-render-injection

Author
3,077
Download Count*
License
User controllable data $REQ
enters $RES.render(...)
this can lead to the loading of other HTML/templating pages that they may not be authorized to render. An attacker may attempt to use directory traversal techniques e.g. ../folder/index
to access other HTML pages on the file system. Where possible, do not allow users to define what should be loaded in $RES.render or use an allow list for the existing application.
Run Locally
Run in CI
Defintion
rules:
- id: res-render-injection
message: User controllable data `$REQ` enters `$RES.render(...)` this can lead
to the loading of other HTML/templating pages that they may not be
authorized to render. An attacker may attempt to use directory traversal
techniques e.g. `../folder/index` to access other HTML pages on the file
system. Where possible, do not allow users to define what should
be loaded in $RES.render or use an allow list for the existing
application.
metadata:
interfile: true
owasp:
- A01:2021 - Broken Access Control
cwe:
- "CWE-706: Use of Incorrectly-Resolved Name or Reference"
category: security
technology:
- express
references:
- http://expressjs.com/en/4x/api.html#res.render
subcategory:
- vuln
likelihood: MEDIUM
impact: MEDIUM
confidence: MEDIUM
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
languages:
- javascript
- typescript
severity: WARNING
mode: taint
pattern-sources:
- patterns:
- pattern-either:
- pattern-inside: function ... ($REQ, $RES) {...}
- pattern-inside: function ... ($REQ, $RES, $NEXT) {...}
- patterns:
- pattern-either:
- pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...})
- pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...})
- metavariable-regex:
metavariable: $METHOD
regex: ^(get|post|put|head|delete|options)$
- pattern-either:
- pattern: $REQ.query
- pattern: $REQ.body
- pattern: $REQ.params
- pattern: $REQ.cookies
- pattern: $REQ.headers
- patterns:
- pattern-either:
- pattern-inside: |
({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) =>
{...}
- pattern-inside: |
({ $REQ }: Request,$RES: Response) => {...}
- focus-metavariable: $REQ
- pattern-either:
- pattern: params
- pattern: query
- pattern: cookies
- pattern: headers
- pattern: body
pattern-sinks:
- patterns:
- pattern-either:
- pattern: $RES.render($SINK, ...)
- focus-metavariable: $SINK
Examples
res-render-injection.js
const express = require('express')
const app = express()
const port = 3000
const hardcodedPath = 'lib/layout'
function testController1(req, res) {
// ruleid: res-render-injection
return res.render(`tpl.${req.query.path}`, {foo: bar})
};
app.get('/test1', testController1)
app.get('/test2', (req, res) => {
// ruleid: res-render-injection
return res.render('tpl.' + req.query.path + '.smth-else', {foo: bar})
})
app.get('/ok-test', (req, res) => {
// ok: res-render-injection
return res.render(hardcodedPath, {foo: bar})
})
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
Short Link: https://sg.run/eLjd