Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 65907c9

Browse files
committed
Python: Copy Xxe/XmlBomb queries from JS
After internal discussion, these will replace the `XmlEntityInjection` query, so we can have separate severities on DoS and the other (more serious) attacks. Note: These clearly don't work, since they are verbatim copies of the JS code, but I split it into multiple commits to clearly highlight what changes were made.
1 parent 48015e5 commit 65907c9

12 files changed

Lines changed: 352 additions & 0 deletions

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
2+
<qhelp>
3+
4+
<overview>
5+
<p>
6+
Parsing untrusted XML files with a weakly configured XML parser may lead to an
7+
XML External Entity (XXE) attack. This type of attack uses external entity references
8+
to access arbitrary files on a system, carry out denial-of-service (DoS) attacks, or server-side
9+
request forgery. Even when the result of parsing is not returned to the user, DoS attacks are still possible
10+
and out-of-band data retrieval techniques may allow attackers to steal sensitive data.
11+
</p>
12+
</overview>
13+
14+
<recommendation>
15+
<p>
16+
The easiest way to prevent XXE attacks is to disable external entity handling when
17+
parsing untrusted data. How this is done depends on the library being used. Note that some
18+
libraries, such as recent versions of <code>libxml</code>, disable entity expansion by default,
19+
so unless you have explicitly enabled entity expansion, no further action needs to be taken.
20+
</p>
21+
</recommendation>
22+
23+
<example>
24+
<p>
25+
The following example uses the <code>libxml</code> XML parser to parse a string <code>xmlSrc</code>.
26+
If that string is from an untrusted source, this code may be vulnerable to an XXE attack, since
27+
the parser is invoked with the <code>noent</code> option set to <code>true</code>:
28+
</p>
29+
<sample src="examples/Xxe.js"/>
30+
31+
<p>
32+
To guard against XXE attacks, the <code>noent</code> option should be omitted or set to
33+
<code>false</code>. This means that no entity expansion is undertaken at all, not even for standard
34+
internal entities such as <code>&amp;amp;</code> or <code>&amp;gt;</code>. If desired, these
35+
entities can be expanded in a separate step using utility functions provided by libraries such
36+
as <a href="http://underscorejs.org/#unescape">underscore</a>,
37+
<a href="https://lodash.com/docs/4.17.15#unescape">lodash</a> or
38+
<a href="https://github.com/mathiasbynens/he">he</a>.
39+
</p>
40+
<sample src="examples/XxeGood.js"/>
41+
</example>
42+
43+
<references>
44+
<li>
45+
OWASP:
46+
<a href="https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing">XML External Entity (XXE) Processing</a>.
47+
</li>
48+
<li>
49+
Timothy Morgen:
50+
<a href="https://research.nccgroup.com/2014/05/19/xml-schema-dtd-and-entity-attacks-a-compendium-of-known-techniques/">XML Schema, DTD, and Entity Attacks</a>.
51+
</li>
52+
<li>
53+
Timur Yunusov, Alexey Osipov:
54+
<a href="https://www.slideshare.net/qqlan/bh-ready-v4">XML Out-Of-Band Data Retrieval</a>.
55+
</li>
56+
</references>
57+
</qhelp>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* @name XML external entity expansion
3+
* @description Parsing user input as an XML document with external
4+
* entity expansion is vulnerable to XXE attacks.
5+
* @kind path-problem
6+
* @problem.severity error
7+
* @security-severity 9.1
8+
* @precision high
9+
* @id js/xxe
10+
* @tags security
11+
* external/cwe/cwe-611
12+
* external/cwe/cwe-827
13+
*/
14+
15+
import javascript
16+
import semmle.javascript.security.dataflow.XxeQuery
17+
import DataFlow::PathGraph
18+
19+
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
20+
where cfg.hasFlowPath(source, sink)
21+
select sink.getNode(), source, sink,
22+
"A $@ is parsed as XML without guarding against external entity expansion.", source.getNode(),
23+
"user-provided value"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const app = require("express")(),
2+
libxml = require("libxmljs");
3+
4+
app.post("upload", (req, res) => {
5+
let xmlSrc = req.body,
6+
doc = libxml.parseXml(xmlSrc, { noent: true });
7+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const app = require("express")(),
2+
libxml = require("libxmljs");
3+
4+
app.post("upload", (req, res) => {
5+
let xmlSrc = req.body,
6+
doc = libxml.parseXml(xmlSrc);
7+
});
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
2+
<qhelp>
3+
4+
<overview>
5+
<p>
6+
Parsing untrusted XML files with a weakly configured XML parser may be vulnerable to
7+
denial-of-service (DoS) attacks exploiting uncontrolled internal entity expansion.
8+
</p>
9+
<p>
10+
In XML, so-called <i>internal entities</i> are a mechanism for introducing an abbreviation
11+
for a piece of text or part of a document. When a parser that has been configured
12+
to expand entities encounters a reference to an internal entity, it replaces the entity
13+
by the data it represents. The replacement text may itself contain other entity references,
14+
which are expanded recursively. This means that entity expansion can increase document size
15+
dramatically.
16+
</p>
17+
<p>
18+
If untrusted XML is parsed with entity expansion enabled, a malicious attacker could
19+
submit a document that contains very deeply nested entity definitions, causing the parser
20+
to take a very long time or use large amounts of memory. This is sometimes called an
21+
<i>XML bomb</i> attack.
22+
</p>
23+
</overview>
24+
25+
<recommendation>
26+
<p>
27+
The safest way to prevent XML bomb attacks is to disable entity expansion when parsing untrusted
28+
data. How this is done depends on the library being used. Note that some libraries, such as
29+
recent versions of <code>libxmljs</code> (though not its SAX parser API), disable entity expansion
30+
by default, so unless you have explicitly enabled entity expansion, no further action is needed.
31+
</p>
32+
</recommendation>
33+
34+
<example>
35+
<p>
36+
The following example uses the XML parser provided by the <code>node-expat</code> package to
37+
parse a string <code>xmlSrc</code>. If that string is from an untrusted source, this code may be
38+
vulnerable to a DoS attack, since <code>node-expat</code> expands internal entities by default:
39+
</p>
40+
<sample src="examples/XmlBomb.js"/>
41+
42+
<p>
43+
At the time of writing, <code>node-expat</code> does not provide a way of controlling entity
44+
expansion, but the example could be rewritten to use the <code>sax</code> package instead,
45+
which only expands standard entities such as <code>&amp;amp;</code>:
46+
</p>
47+
<sample src="examples/XmlBombGood.js"/>
48+
</example>
49+
50+
<references>
51+
<li>
52+
Wikipedia:
53+
<a href="https://en.wikipedia.org/wiki/Billion_laughs">Billion Laughs</a>.
54+
</li>
55+
<li>
56+
Bryan Sullivan:
57+
<a href="https://msdn.microsoft.com/en-us/magazine/ee335713.aspx">Security Briefs - XML Denial of Service Attacks and Defenses</a>.
58+
</li>
59+
</references>
60+
</qhelp>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* @name XML internal entity expansion
3+
* @description Parsing user input as an XML document with arbitrary internal
4+
* entity expansion is vulnerable to denial-of-service attacks.
5+
* @kind path-problem
6+
* @problem.severity warning
7+
* @security-severity 7.5
8+
* @precision high
9+
* @id js/xml-bomb
10+
* @tags security
11+
* external/cwe/cwe-776
12+
* external/cwe/cwe-400
13+
*/
14+
15+
import javascript
16+
import semmle.javascript.security.dataflow.XmlBombQuery
17+
import DataFlow::PathGraph
18+
19+
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
20+
where cfg.hasFlowPath(source, sink)
21+
select sink.getNode(), source, sink,
22+
"A $@ is parsed as XML without guarding against uncontrolled entity expansion.", source.getNode(),
23+
"user-provided value"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const app = require("express")(),
2+
expat = require("node-expat");
3+
4+
app.post("upload", (req, res) => {
5+
let xmlSrc = req.body,
6+
parser = new expat.Parser();
7+
parser.on("startElement", handleStart);
8+
parser.on("text", handleText);
9+
parser.write(xmlSrc);
10+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const app = require("express")(),
2+
sax = require("sax");
3+
4+
app.post("upload", (req, res) => {
5+
let xmlSrc = req.body,
6+
parser = sax.parser(true);
7+
parser.onopentag = handleStart;
8+
parser.ontext = handleText;
9+
parser.write(xmlSrc);
10+
});
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Provides default sources, sinks and sanitizers for reasoning about
3+
* XML-bomb vulnerabilities, as well as extension points for adding
4+
* your own.
5+
*/
6+
7+
import javascript
8+
import semmle.javascript.security.dataflow.DOM
9+
10+
module XmlBomb {
11+
/**
12+
* A data flow source for XML-bomb vulnerabilities.
13+
*/
14+
abstract class Source extends DataFlow::Node { }
15+
16+
/**
17+
* A data flow sink for XML-bomb vulnerabilities.
18+
*/
19+
abstract class Sink extends DataFlow::Node { }
20+
21+
/**
22+
* A sanitizer for XML-bomb vulnerabilities.
23+
*/
24+
abstract class Sanitizer extends DataFlow::Node { }
25+
26+
/** A source of remote user input, considered as a flow source for XML bomb vulnerabilities. */
27+
class RemoteFlowSourceAsSource extends Source {
28+
RemoteFlowSourceAsSource() { this instanceof RemoteFlowSource }
29+
}
30+
31+
/**
32+
* An access to `document.location`, considered as a flow source for XML bomb vulnerabilities.
33+
*/
34+
class LocationAsSource extends Source, DataFlow::ValueNode {
35+
LocationAsSource() { isLocation(astNode) }
36+
}
37+
38+
/**
39+
* A call to an XML parser that performs internal entity expansion, viewed
40+
* as a data flow sink for XML-bomb vulnerabilities.
41+
*/
42+
class XmlParsingWithEntityResolution extends Sink, DataFlow::ValueNode {
43+
XmlParsingWithEntityResolution() {
44+
exists(XML::ParserInvocation parse | astNode = parse.getSourceArgument() |
45+
parse.resolvesEntities(XML::InternalEntity())
46+
)
47+
}
48+
}
49+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Provides a taint tracking configuration for reasoning about
3+
* XML-bomb vulnerabilities.
4+
*
5+
* Note, for performance reasons: only import this file if
6+
* `XmlBomb::Configuration` is needed, otherwise
7+
* `XmlBombCustomizations` should be imported instead.
8+
*/
9+
10+
import javascript
11+
import XmlBombCustomizations::XmlBomb
12+
13+
/**
14+
* A taint-tracking configuration for reasoning about XML-bomb vulnerabilities.
15+
*/
16+
class Configuration extends TaintTracking::Configuration {
17+
Configuration() { this = "XmlBomb" }
18+
19+
override predicate isSource(DataFlow::Node source) { source instanceof Source }
20+
21+
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
22+
23+
override predicate isSanitizer(DataFlow::Node node) {
24+
super.isSanitizer(node) or
25+
node instanceof Sanitizer
26+
}
27+
}

0 commit comments

Comments
 (0)