contrib.nodejsscan.header_injection.generic_header_injection

Author
99
Download Count*
License
Untrusted user input in response header will result in HTTP Header Injection or Response Splitting Attacks.
Run Locally
Run in CI
Defintion
rules:
- id: generic_header_injection
patterns:
- pattern-either:
- pattern-inside: function ($REQ, $RES, ...) {...}
- pattern-inside: function $FUNC($REQ, $RES, ...) {...}
- pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...}
- pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...};
- pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...})
- pattern-either:
- pattern: |
$INP = $REQ.$QUERY;
...
$RES.set(..., <... $INP ...>, ...);
- pattern: |
$INP = $REQ.$QUERY.$VAR;
...
$RES.set(..., <... $INP ...>, ...);
- pattern: |
$INP = $REQ.$VAR;
...
$RES.set(..., { $X: <... $INP ...>}, ...);
- pattern: |
$INP = $REQ.$QUERY.$FOO;
...
$RES.set(..., { $X: <... $INP ...>}, ...);
- pattern: |
$INP = $REQ.$VAR;
...
$RES.writeHead(..., { $X: <... $INP ...> }, ...);
- pattern: |
$INP = $REQ.$QUERY.$FOO;
...
$RES.writeHead(..., { $X: <... $INP ...> }, ...);
- pattern: |
$RES.set(..., <... $REQ.$QUERY ...>, ...)
- pattern: |
$RES.set(..., <... $REQ.$QUERY.$VAR ...>, ...)
- pattern: |
$RES.set(..., { $X: <... $REQ.$VAR ...>}, ...)
- pattern: |
$RES.set(..., { $X: <... $REQ.$QUERY.$FOO ...>}, ...);
- pattern: |
$RES.writeHead(..., { $X: <... $REQ.$VAR ...> }, ...);
- pattern: |
$RES.writeHead(..., { $X: <... $REQ.$QUERY.$FOO ...> }, ...);
message: Untrusted user input in response header will result in HTTP Header
Injection or Response Splitting Attacks.
languages:
- javascript
severity: ERROR
metadata:
owasp: A01:2017 - Injection
cwe: "CWE-644: Improper Neutralization of HTTP Headers for Scripting Syntax"
category: security
technology:
- node.js
- express
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
Examples
header_injection.js
var server = http.createServer(function (req, res) {
var bla = 'dsdsd';
switch (testIndex++) {
case 0:
// ruleid:generic_header_injection
res.writeHead(200, { test: 'foo \r\ninvalid: bar' + req.foo });
break;
case 1:
// ruleid:generic_header_injection
res.writeHead(200, { test: req.foo + 'foo \ninvalid: bar' });
break;
case 2:
// ruleid:generic_header_injection
res.writeHead(200, { test: 'foo \rinvalid: bar' + req.foo + 'asdadasd', foo: bar });
break;
case 3:
// ruleid:generic_header_injection
res.writeHead(200, { test: bla + 'foo \n\n\ninvalid: bar' + req.foo });
break;
case 5:
// ruleid:generic_header_injection
res.writeHead(200, { test: bla + 'foo \n\n\ninvalid: bar' + req.foo('asd') });
break;
case 4:
// ruleid:generic_header_injection
res.writeHead(200, { test: req.foo });
server.close();
break;
default:
assert(false);
}
res.end('Hi mars!');
});
server.listen(common.PORT);
var express = require('express');
var app = express();
app.get('/', function (req, res) {
// ruleid:generic_header_injection
res.writeHead(200, { test: 'foo \r\ninvalid: bar' + req.foo });
// ruleid:generic_header_injection
res.set('Content-Type', req.query.foo);
// ruleid:generic_header_injection
res.set('foo', 'asdad' + req.query.foo);
// ruleid:generic_header_injection
res.set(req.query.foo, 'asdadad');
// ruleid:generic_header_injection
res.set('asda' + req.query.foo, 'asdadad');
// ruleid:generic_header_injection
res.set('asda' + req.query["foo"], 'asdadad');
// ruleid:generic_header_injection
res.set('asda' + req.query("foo"), 'asdadad');
// ruleid:generic_header_injection
res.set({
'Content-Type': 'text/plain',
'Content-Length': req.query.foo,
'ETag': '12345'
})
//do not detect
res.writeHead(200, { tast: ddd })
res.set(ffff)
});
Short Link: https://sg.run/OPZw