diff --git a/python/ql/test/experimental/query-tests/Security/CWE-611-Xxe/Xxe.expected b/python/ql/test/experimental/query-tests/Security/CWE-611-Xxe/Xxe.expected new file mode 100644 index 00000000000..004369d79cf --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-611-Xxe/Xxe.expected @@ -0,0 +1,20 @@ +edges +| test.py:8:19:8:25 | ControlFlowNode for request | test.py:8:19:8:30 | ControlFlowNode for Attribute | +| test.py:8:19:8:30 | ControlFlowNode for Attribute | test.py:8:19:8:45 | ControlFlowNode for Subscript | +| test.py:8:19:8:45 | ControlFlowNode for Subscript | test.py:9:34:9:44 | ControlFlowNode for xml_content | +| test.py:19:19:19:25 | ControlFlowNode for request | test.py:19:19:19:30 | ControlFlowNode for Attribute | +| test.py:19:19:19:30 | ControlFlowNode for Attribute | test.py:19:19:19:45 | ControlFlowNode for Subscript | +| test.py:19:19:19:45 | ControlFlowNode for Subscript | test.py:30:34:30:44 | ControlFlowNode for xml_content | +nodes +| test.py:8:19:8:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test.py:8:19:8:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:8:19:8:45 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:9:34:9:44 | ControlFlowNode for xml_content | semmle.label | ControlFlowNode for xml_content | +| test.py:19:19:19:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test.py:19:19:19:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:19:19:19:45 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:30:34:30:44 | ControlFlowNode for xml_content | semmle.label | ControlFlowNode for xml_content | +subpaths +#select +| test.py:9:34:9:44 | ControlFlowNode for xml_content | test.py:8:19:8:25 | ControlFlowNode for request | test.py:9:34:9:44 | ControlFlowNode for xml_content | A $@ is parsed as XML without guarding against external entity expansion. | test.py:8:19:8:25 | ControlFlowNode for request | user-provided value | +| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:19:19:19:25 | ControlFlowNode for request | test.py:30:34:30:44 | ControlFlowNode for xml_content | A $@ is parsed as XML without guarding against external entity expansion. | test.py:19:19:19:25 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-611-Xxe/Xxe.qlref b/python/ql/test/experimental/query-tests/Security/CWE-611-Xxe/Xxe.qlref new file mode 100644 index 00000000000..f8a07d7d2ee --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-611-Xxe/Xxe.qlref @@ -0,0 +1 @@ +experimental/Security/NEW/CWE-611/Xxe.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-611-Xxe/test.py b/python/ql/test/experimental/query-tests/Security/CWE-611-Xxe/test.py new file mode 100644 index 00000000000..d9181c4cf34 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-611-Xxe/test.py @@ -0,0 +1,30 @@ +from flask import Flask, request +import lxml.etree + +app = Flask(__name__) + +@app.route("/vuln-handler") +def vuln_handler(): + xml_content = request.args['xml_content'] + return lxml.etree.fromstring(xml_content).text + +@app.route("/safe-handler") +def safe_handler(): + xml_content = request.args['xml_content'] + parser = lxml.etree.XMLParser(resolve_entities=False) + return lxml.etree.fromstring(xml_content, parser=parser).text + +@app.route("/super-vuln-handler") +def super_vuln_handler(): + xml_content = request.args['xml_content'] + parser = lxml.etree.XMLParser( + # allows XXE + resolve_entities=True, + # allows remote XXE + no_network=False, + # together with `no_network=False`, allows DTD-retrival + load_dtd=True, + # allows DoS attacks + huge_tree=True, + ) + return lxml.etree.fromstring(xml_content, parser=parser).text diff --git a/python/ql/test/experimental/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected b/python/ql/test/experimental/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected new file mode 100644 index 00000000000..15c439d0761 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected @@ -0,0 +1,12 @@ +edges +| test.py:19:19:19:25 | ControlFlowNode for request | test.py:19:19:19:30 | ControlFlowNode for Attribute | +| test.py:19:19:19:30 | ControlFlowNode for Attribute | test.py:19:19:19:45 | ControlFlowNode for Subscript | +| test.py:19:19:19:45 | ControlFlowNode for Subscript | test.py:30:34:30:44 | ControlFlowNode for xml_content | +nodes +| test.py:19:19:19:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test.py:19:19:19:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:19:19:19:45 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:30:34:30:44 | ControlFlowNode for xml_content | semmle.label | ControlFlowNode for xml_content | +subpaths +#select +| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:19:19:19:25 | ControlFlowNode for request | test.py:30:34:30:44 | ControlFlowNode for xml_content | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | test.py:19:19:19:25 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-776-XmlBomb/XmlBomb.qlref b/python/ql/test/experimental/query-tests/Security/CWE-776-XmlBomb/XmlBomb.qlref new file mode 100644 index 00000000000..5eadbb1f26f --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-776-XmlBomb/XmlBomb.qlref @@ -0,0 +1 @@ +experimental/Security/NEW/CWE-776/XmlBomb.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-776-XmlBomb/test.py b/python/ql/test/experimental/query-tests/Security/CWE-776-XmlBomb/test.py new file mode 100644 index 00000000000..d9181c4cf34 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-776-XmlBomb/test.py @@ -0,0 +1,30 @@ +from flask import Flask, request +import lxml.etree + +app = Flask(__name__) + +@app.route("/vuln-handler") +def vuln_handler(): + xml_content = request.args['xml_content'] + return lxml.etree.fromstring(xml_content).text + +@app.route("/safe-handler") +def safe_handler(): + xml_content = request.args['xml_content'] + parser = lxml.etree.XMLParser(resolve_entities=False) + return lxml.etree.fromstring(xml_content, parser=parser).text + +@app.route("/super-vuln-handler") +def super_vuln_handler(): + xml_content = request.args['xml_content'] + parser = lxml.etree.XMLParser( + # allows XXE + resolve_entities=True, + # allows remote XXE + no_network=False, + # together with `no_network=False`, allows DTD-retrival + load_dtd=True, + # allows DoS attacks + huge_tree=True, + ) + return lxml.etree.fromstring(xml_content, parser=parser).text