diff --git a/python/ql/src/experimental/Security/NEW/CWE-776/XmlBomb.qhelp b/python/ql/src/experimental/Security/NEW/CWE-776/XmlBomb.qhelp index c0714b3f96f..f20dd526fdd 100644 --- a/python/ql/src/experimental/Security/NEW/CWE-776/XmlBomb.qhelp +++ b/python/ql/src/experimental/Security/NEW/CWE-776/XmlBomb.qhelp @@ -25,26 +25,32 @@ to take a very long time or use large amounts of memory. This is sometimes calle

The safest way to prevent XML bomb attacks is to disable entity expansion when parsing untrusted -data. How this is done depends on the library being used. Note that some libraries, such as -recent versions of libxmljs (though not its SAX parser API), disable entity expansion -by default, so unless you have explicitly enabled entity expansion, no further action is needed. +data. Whether this can be done depends on the library being used. Note that some libraries, such as +lxml, have measures enabled by default to prevent such DoS XML attacks, so +unless you have explicitly set huge_tree to True, no further action is needed. +

+ +

+We recommend using the defusedxml +PyPI package, which has been created to prevent XML attacks (both XXE and XML bombs).

-The following example uses the XML parser provided by the node-expat package to -parse a string xmlSrc. If that string is from an untrusted source, this code may be -vulnerable to a DoS attack, since node-expat expands internal entities by default: +The following example uses the xml.etree XML parser provided by the Python standard library to +parse a string xml_src. That string is from an untrusted source, so this code is be +vulnerable to a DoS attack, since the xml.etree XML parser expands internal entities by default:

- +

-At the time of writing, node-expat does not provide a way of controlling entity -expansion, but the example could be rewritten to use the sax package instead, -which only expands standard entities such as &: +It is not possible to guard against internal entity expansion with +xml.etree, so to guard against these attacks, the following example uses +the defusedxml +PyPI package instead, which is not exposed to such internal entity expansion attacks.

- +
@@ -56,5 +62,13 @@ Wikipedia: Bryan Sullivan: Security Briefs - XML Denial of Service Attacks and Defenses. +
  • +Python 3 standard library: +XML Vulnerabilities. +
  • +
  • +Python 2 standard library: +XML Vulnerabilities. +
  • diff --git a/python/ql/src/experimental/Security/NEW/CWE-776/examples/XmlBomb.js b/python/ql/src/experimental/Security/NEW/CWE-776/examples/XmlBomb.js deleted file mode 100644 index f72902a5304..00000000000 --- a/python/ql/src/experimental/Security/NEW/CWE-776/examples/XmlBomb.js +++ /dev/null @@ -1,10 +0,0 @@ -const app = require("express")(), - expat = require("node-expat"); - -app.post("upload", (req, res) => { - let xmlSrc = req.body, - parser = new expat.Parser(); - parser.on("startElement", handleStart); - parser.on("text", handleText); - parser.write(xmlSrc); -}); diff --git a/python/ql/src/experimental/Security/NEW/CWE-776/examples/XmlBombBad.py b/python/ql/src/experimental/Security/NEW/CWE-776/examples/XmlBombBad.py new file mode 100644 index 00000000000..d52054d9492 --- /dev/null +++ b/python/ql/src/experimental/Security/NEW/CWE-776/examples/XmlBombBad.py @@ -0,0 +1,10 @@ +from flask import Flask, request +import xml.etree.ElementTree as ET + +app = Flask(__name__) + +@app.post("/upload") +def upload(): + xml_src = request.get_data() + doc = ET.fromstring(xml_src) + return ET.tostring(doc) diff --git a/python/ql/src/experimental/Security/NEW/CWE-776/examples/XmlBombGood.js b/python/ql/src/experimental/Security/NEW/CWE-776/examples/XmlBombGood.js deleted file mode 100644 index a8c5bc97e63..00000000000 --- a/python/ql/src/experimental/Security/NEW/CWE-776/examples/XmlBombGood.js +++ /dev/null @@ -1,10 +0,0 @@ -const app = require("express")(), - sax = require("sax"); - -app.post("upload", (req, res) => { - let xmlSrc = req.body, - parser = sax.parser(true); - parser.onopentag = handleStart; - parser.ontext = handleText; - parser.write(xmlSrc); -}); diff --git a/python/ql/src/experimental/Security/NEW/CWE-776/examples/XmlBombGood.py b/python/ql/src/experimental/Security/NEW/CWE-776/examples/XmlBombGood.py new file mode 100644 index 00000000000..5e4261e35da --- /dev/null +++ b/python/ql/src/experimental/Security/NEW/CWE-776/examples/XmlBombGood.py @@ -0,0 +1,10 @@ +from flask import Flask, request +import defusedxml.ElementTree as ET + +app = Flask(__name__) + +@app.post("/upload") +def upload(): + xml_src = request.get_data() + doc = ET.fromstring(xml_src) + return ET.tostring(doc)