javascript.express.security.express-xml2json-xxe.express-xml2json-xxe

Author
3,077
Download Count*
License
Make sure that unverified user data can not reach the XML Parser, as it can result in XML External or Internal Entity (XXE) Processing vulnerabilities
Run Locally
Run in CI
Defintion
rules:
- id: express-xml2json-xxe
message: Make sure that unverified user data can not reach the XML Parser, as it
can result in XML External or Internal Entity (XXE) Processing
vulnerabilities
metadata:
owasp:
- A04:2017 - XML External Entities (XXE)
- A05:2021 - Security Misconfiguration
cwe:
- "CWE-611: Improper Restriction of XML External Entity Reference"
asvs:
section: V5 Validation, Sanitization and Encoding
control_id: 5.5.2 Insecue XML Deserialization
control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention
version: "4"
category: security
technology:
- express
references:
- https://www.npmjs.com/package/xml2json
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- vuln
likelihood: MEDIUM
impact: MEDIUM
confidence: MEDIUM
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
languages:
- javascript
- typescript
severity: ERROR
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
- pattern: $REQ.files.$ANYTHING.data.toString('utf8')
- pattern: $REQ.files.$ANYTHING['data'].toString('utf8')
- 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: files.$ANYTHING.data.toString('utf8')
- pattern: files.$ANYTHING['data'].toString('utf8')
pattern-sinks:
- patterns:
- pattern-either:
- pattern-inside: |
require('xml2json');
...
- pattern-inside: |
import 'xml2json';
...
- pattern: $EXPAT.toJson($SINK,...)
- focus-metavariable: $SINK
Examples
express-xml2json-xxe.js
function test1() {
const express = require('express')
const xml2json = require('xml2json')
const app = express()
const port = 3000
app.get('/', (req, res) => {
const xml = req.query.xml
// ruleid: express-xml2json-xxe
const content = xml2json.toJson(xml, {coerce: true, object: true});
res.send(content)
})
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
}
function test2() {
const express = require('express')
const xml2json = require('xml2json')
const app = express()
const port = 3000
app.get('/', (req, res) => {
// ruleid: express-xml2json-xxe
const content = xml2json.toJson(req.body, {coerce: true, object: true});
res.send(content)
})
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
}
function okTest() {
const express = require('express')
const xml2json = require('xml2json')
const app = express()
const port = 3000
app.get('/', (req, res) => {
// ok: express-xml2json-xxe
const content = expat.toJson(someVerifiedData(), {coerce: true, object: true});
res.send(content)
})
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
}
Short Link: https://sg.run/XBD4