From 1ceb963d4c11c4cbabf3a9e621afd74f011158a7 Mon Sep 17 00:00:00 2001 From: Porcupiney Hairs Date: Wed, 20 May 2020 02:03:38 +0530 Subject: [PATCH 1/4] Python : Add support for detecting XSLT Injection This PR adds support for detecting XSLT injection in Python. I have included the ql files as well as the tests with this. --- python/ql/src/experimental/CWE-643/Xslt.qhelp | 16 +++ python/ql/src/experimental/CWE-643/Xslt.ql | 35 ++++++ python/ql/src/experimental/CWE-643/xslt.py | 14 +++ .../semmle/python/security/injection/XSLT.qll | 119 ++++++++++++++++++ .../test/experimental/CWE-074/Xslt.expected | 47 +++++++ .../ql/test/experimental/CWE-074/Xslt.qlref | 1 + .../experimental/CWE-074/XsltSinks.expected | 12 ++ .../ql/test/experimental/CWE-074/XsltSinks.ql | 6 + python/ql/test/experimental/CWE-074/options | 1 + python/ql/test/experimental/CWE-074/xslt.py | 14 +++ .../experimental/CWE-074/xsltInjection.py | 79 ++++++++++++ .../ql/test/experimental/CWE-074/xsltSinks.py | 56 +++++++++ .../query-tests/Security/lib/lxml/__init__.py | 0 .../query-tests/Security/lib/lxml/etree.py | 37 ++++++ 14 files changed, 437 insertions(+) create mode 100644 python/ql/src/experimental/CWE-643/Xslt.qhelp create mode 100644 python/ql/src/experimental/CWE-643/Xslt.ql create mode 100644 python/ql/src/experimental/CWE-643/xslt.py create mode 100644 python/ql/src/experimental/semmle/python/security/injection/XSLT.qll create mode 100644 python/ql/test/experimental/CWE-074/Xslt.expected create mode 100644 python/ql/test/experimental/CWE-074/Xslt.qlref create mode 100644 python/ql/test/experimental/CWE-074/XsltSinks.expected create mode 100644 python/ql/test/experimental/CWE-074/XsltSinks.ql create mode 100644 python/ql/test/experimental/CWE-074/options create mode 100644 python/ql/test/experimental/CWE-074/xslt.py create mode 100644 python/ql/test/experimental/CWE-074/xsltInjection.py create mode 100644 python/ql/test/experimental/CWE-074/xsltSinks.py create mode 100644 python/ql/test/query-tests/Security/lib/lxml/__init__.py create mode 100644 python/ql/test/query-tests/Security/lib/lxml/etree.py diff --git a/python/ql/src/experimental/CWE-643/Xslt.qhelp b/python/ql/src/experimental/CWE-643/Xslt.qhelp new file mode 100644 index 000000000000..cdcc7e4dada5 --- /dev/null +++ b/python/ql/src/experimental/CWE-643/Xslt.qhelp @@ -0,0 +1,16 @@ + + + + Processing an unvalidated XSL stylesheet can allow an attacker to change the structure and contents of the resultant XML, include arbitrary files from the file system, or execute arbitrary code. + + +

+ This vulnerability can be prevented by not allowing untrusted user input to be passed as a XSL stylesheet. + If the application logic necessiates processing untrusted XSL stylesheets, the input should be properly filtered and sanitized before use. +

+ +

In the example below, the XSL stylesheet is controlled by the user and hence leads to a vulnerability.

+ +
+
+
\ No newline at end of file diff --git a/python/ql/src/experimental/CWE-643/Xslt.ql b/python/ql/src/experimental/CWE-643/Xslt.ql new file mode 100644 index 000000000000..09345858160e --- /dev/null +++ b/python/ql/src/experimental/CWE-643/Xslt.ql @@ -0,0 +1,35 @@ +/** + * @name Xslt query built from user-controlled sources + * @description Building a XSLT query from user-controlled sources is vulnerable to insertion of + * malicious XSLT code by the user. + * @kind path-problem + * @problem.severity error + * @precision high + * @id py/xslt-injection + * @tags security + * external/cwe/cwe-643 + */ + +import python +import semmle.python.security.Paths +/* Sources */ +import semmle.python.web.HttpRequest +/* Sinks */ +import experimental.semmle.python.security.injection.XSLT + +class XSLTInjectionConfiguration extends TaintTracking::Configuration { + XSLTInjectionConfiguration() { this = "XSLT injection configuration" } + + override predicate isSource(TaintTracking::Source source) { + source instanceof HttpRequestTaintSource + } + + override predicate isSink(TaintTracking::Sink sink) { + sink instanceof XSLTInjection::XSLTInjectionSink + } +} + +from XSLTInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink +where config.hasFlowPath(src, sink) +select sink.getSink(), src, sink, "This XSLT query depends on $@.", src.getSource(), + "a user-provided value" diff --git a/python/ql/src/experimental/CWE-643/xslt.py b/python/ql/src/experimental/CWE-643/xslt.py new file mode 100644 index 000000000000..1655916c7e06 --- /dev/null +++ b/python/ql/src/experimental/CWE-643/xslt.py @@ -0,0 +1,14 @@ +from lxml import etree +from io import StringIO +from flask import Flask, request + +app = Flask(__name__) + + +@app.route("/xslt") +def bad(): + xsltQuery = request.args.get('xml', '') + xslt_root = etree.XML(xsltQuery) + f = StringIO('') + tree = etree.parse(f) + result_tree = tree.xslt(xslt_root) # Not OK diff --git a/python/ql/src/experimental/semmle/python/security/injection/XSLT.qll b/python/ql/src/experimental/semmle/python/security/injection/XSLT.qll new file mode 100644 index 000000000000..795d439d83a4 --- /dev/null +++ b/python/ql/src/experimental/semmle/python/security/injection/XSLT.qll @@ -0,0 +1,119 @@ +/** + * Provides class and predicates to track external data that + * may represent malicious XSLT query objects. + * + * This module is intended to be imported into a taint-tracking query + * to extend `TaintKind` and `TaintSink`. + */ + +import python +import semmle.python.security.TaintTracking +import semmle.python.web.HttpRequest + +/** Models XSLT Injection related classes and functions */ +module XSLTInjection { + /** Returns a class value which refers to `lxml.etree` */ + Value etree() { result = Value::named("lxml.etree") } + + /** A generic taint sink that is vulnerable to XSLT injection. */ + abstract class XSLTInjectionSink extends TaintSink { } + + /** + * A kind of "taint", representing an untrusted XML string + */ + private class ExternalXmlStringKind extends ExternalStringKind { + ExternalXmlStringKind() { this = "etree.XML string" } + + override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { + etreeXML(fromnode, tonode) and result instanceof ExternalXmlKind + or + etreeFromStringList(fromnode, tonode) and result instanceof ExternalXmlKind + or + etreeFromString(fromnode, tonode) and result instanceof ExternalXmlKind + } + } + + /** + * A kind of "taint", representing a XML encoded string + */ + class ExternalXmlKind extends TaintKind { + ExternalXmlKind() { this = "lxml etree xml" } + } + + private predicate etreeXML(ControlFlowNode fromnode, CallNode tonode) { + exists(CallNode call, AttrNode atr | + atr = etree().getAReference().getASuccessor() and + // XML(text, parser=None, base_url=None) + atr.getName() = "XML" and + atr = call.getFunction() + | + call.getArg(0) = fromnode and + call = tonode + ) + } + + private predicate etreeFromString(ControlFlowNode fromnode, CallNode tonode) { + // fromstring(text, parser=None) + exists(CallNode call | call.getFunction().(AttrNode).getObject("fromstring").pointsTo(etree()) | + call.getArg(0) = fromnode and + call = tonode + ) + } + + private predicate etreeFromStringList(ControlFlowNode fromnode, CallNode tonode) { + // fromstringlist(strings, parser=None) + exists(CallNode call | + call.getFunction().(AttrNode).getObject("fromstringlist").pointsTo(etree()) + | + call.getArg(0) = fromnode and + call = tonode + ) + } + + /** + * A Sink representing an argument to the `etree.XSLT` call. + * + * from lxml import etree + * root = etree.XML("") + * find_text = etree.XSLT("`sink`") + */ + private class EtreeXSLTArgument extends XSLTInjectionSink { + override string toString() { result = "lxml.etree.XSLT" } + + EtreeXSLTArgument() { + exists(CallNode call | call.getFunction().(AttrNode).getObject("XSLT").pointsTo(etree()) | + call.getArg(0) = this + ) + } + + override predicate sinks(TaintKind kind) { kind instanceof ExternalXmlKind } + } + + /** + * A Sink representing an argument to the `XSLT` call to a parsed xml document. + * + * from lxml import etree + * from io import StringIO + * `sink` = etree.XML(xsltQuery) + * tree = etree.parse(f) + * result_tree = tree.xslt(`sink`) + */ + private class ParseXSLTArgument extends XSLTInjectionSink { + override string toString() { result = "lxml.etree.parse.xslt" } + + ParseXSLTArgument() { + exists( + CallNode parseCall, CallNode xsltCall, ControlFlowNode obj, Variable var, AssignStmt assign + | + parseCall.getFunction().(AttrNode).getObject("parse").pointsTo(etree()) and + assign.getValue().(Call).getAFlowNode() = parseCall and + xsltCall.getFunction().(AttrNode).getObject("xslt") = obj and + var.getAUse() = obj and + assign.getATarget() = var.getAStore() and + xsltCall.getArg(0) = this + ) + } + + override predicate sinks(TaintKind kind) { kind instanceof ExternalXmlKind } + } +} diff --git a/python/ql/test/experimental/CWE-074/Xslt.expected b/python/ql/test/experimental/CWE-074/Xslt.expected new file mode 100644 index 000000000000..89f19160f697 --- /dev/null +++ b/python/ql/test/experimental/CWE-074/Xslt.expected @@ -0,0 +1,47 @@ +edges +| xslt.py:10:17:10:28 | dict of etree.XML string | xslt.py:10:17:10:43 | etree.XML string | +| xslt.py:10:17:10:28 | dict of etree.XML string | xslt.py:10:17:10:43 | etree.XML string | +| xslt.py:10:17:10:43 | etree.XML string | xslt.py:11:27:11:35 | etree.XML string | +| xslt.py:10:17:10:43 | etree.XML string | xslt.py:11:27:11:35 | etree.XML string | +| xslt.py:11:17:11:36 | lxml etree xml | xslt.py:14:29:14:37 | lxml etree xml | +| xslt.py:11:17:11:36 | lxml etree xml | xslt.py:14:29:14:37 | lxml etree xml | +| xslt.py:11:27:11:35 | etree.XML string | xslt.py:11:17:11:36 | lxml etree xml | +| xslt.py:11:27:11:35 | etree.XML string | xslt.py:11:17:11:36 | lxml etree xml | +| xsltInjection.py:10:17:10:28 | dict of etree.XML string | xsltInjection.py:10:17:10:43 | etree.XML string | +| xsltInjection.py:10:17:10:28 | dict of etree.XML string | xsltInjection.py:10:17:10:43 | etree.XML string | +| xsltInjection.py:10:17:10:43 | etree.XML string | xsltInjection.py:11:27:11:35 | etree.XML string | +| xsltInjection.py:10:17:10:43 | etree.XML string | xsltInjection.py:11:27:11:35 | etree.XML string | +| xsltInjection.py:11:17:11:36 | lxml etree xml | xsltInjection.py:12:28:12:36 | lxml etree xml | +| xsltInjection.py:11:17:11:36 | lxml etree xml | xsltInjection.py:12:28:12:36 | lxml etree xml | +| xsltInjection.py:11:27:11:35 | etree.XML string | xsltInjection.py:11:17:11:36 | lxml etree xml | +| xsltInjection.py:11:27:11:35 | etree.XML string | xsltInjection.py:11:17:11:36 | lxml etree xml | +| xsltInjection.py:17:17:17:28 | dict of etree.XML string | xsltInjection.py:17:17:17:43 | etree.XML string | +| xsltInjection.py:17:17:17:28 | dict of etree.XML string | xsltInjection.py:17:17:17:43 | etree.XML string | +| xsltInjection.py:17:17:17:43 | etree.XML string | xsltInjection.py:18:27:18:35 | etree.XML string | +| xsltInjection.py:17:17:17:43 | etree.XML string | xsltInjection.py:18:27:18:35 | etree.XML string | +| xsltInjection.py:18:17:18:36 | lxml etree xml | xsltInjection.py:21:29:21:37 | lxml etree xml | +| xsltInjection.py:18:17:18:36 | lxml etree xml | xsltInjection.py:21:29:21:37 | lxml etree xml | +| xsltInjection.py:18:27:18:35 | etree.XML string | xsltInjection.py:18:17:18:36 | lxml etree xml | +| xsltInjection.py:18:27:18:35 | etree.XML string | xsltInjection.py:18:17:18:36 | lxml etree xml | +| xsltInjection.py:26:17:26:28 | dict of etree.XML string | xsltInjection.py:26:17:26:43 | etree.XML string | +| xsltInjection.py:26:17:26:28 | dict of etree.XML string | xsltInjection.py:26:17:26:43 | etree.XML string | +| xsltInjection.py:26:17:26:43 | etree.XML string | xsltInjection.py:27:27:27:35 | etree.XML string | +| xsltInjection.py:26:17:26:43 | etree.XML string | xsltInjection.py:27:27:27:35 | etree.XML string | +| xsltInjection.py:27:17:27:36 | lxml etree xml | xsltInjection.py:31:24:31:32 | lxml etree xml | +| xsltInjection.py:27:17:27:36 | lxml etree xml | xsltInjection.py:31:24:31:32 | lxml etree xml | +| xsltInjection.py:27:27:27:35 | etree.XML string | xsltInjection.py:27:17:27:36 | lxml etree xml | +| xsltInjection.py:27:27:27:35 | etree.XML string | xsltInjection.py:27:17:27:36 | lxml etree xml | +| xsltInjection.py:35:17:35:28 | dict of etree.XML string | xsltInjection.py:35:17:35:43 | etree.XML string | +| xsltInjection.py:35:17:35:28 | dict of etree.XML string | xsltInjection.py:35:17:35:43 | etree.XML string | +| xsltInjection.py:35:17:35:43 | etree.XML string | xsltInjection.py:36:34:36:42 | etree.XML string | +| xsltInjection.py:35:17:35:43 | etree.XML string | xsltInjection.py:36:34:36:42 | etree.XML string | +| xsltInjection.py:36:17:36:43 | lxml etree xml | xsltInjection.py:40:24:40:32 | lxml etree xml | +| xsltInjection.py:36:17:36:43 | lxml etree xml | xsltInjection.py:40:24:40:32 | lxml etree xml | +| xsltInjection.py:36:34:36:42 | etree.XML string | xsltInjection.py:36:17:36:43 | lxml etree xml | +| xsltInjection.py:36:34:36:42 | etree.XML string | xsltInjection.py:36:17:36:43 | lxml etree xml | +#select +| xslt.py:14:29:14:37 | xslt_root | xslt.py:10:17:10:28 | dict of etree.XML string | xslt.py:14:29:14:37 | lxml etree xml | This XSLT query depends on $@. | xslt.py:10:17:10:28 | Attribute | a user-provided value | +| xsltInjection.py:12:28:12:36 | xslt_root | xsltInjection.py:10:17:10:28 | dict of etree.XML string | xsltInjection.py:12:28:12:36 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:10:17:10:28 | Attribute | a user-provided value | +| xsltInjection.py:21:29:21:37 | xslt_root | xsltInjection.py:17:17:17:28 | dict of etree.XML string | xsltInjection.py:21:29:21:37 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:17:17:17:28 | Attribute | a user-provided value | +| xsltInjection.py:31:24:31:32 | xslt_root | xsltInjection.py:26:17:26:28 | dict of etree.XML string | xsltInjection.py:31:24:31:32 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:26:17:26:28 | Attribute | a user-provided value | +| xsltInjection.py:40:24:40:32 | xslt_root | xsltInjection.py:35:17:35:28 | dict of etree.XML string | xsltInjection.py:40:24:40:32 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:35:17:35:28 | Attribute | a user-provided value | diff --git a/python/ql/test/experimental/CWE-074/Xslt.qlref b/python/ql/test/experimental/CWE-074/Xslt.qlref new file mode 100644 index 000000000000..32605307db89 --- /dev/null +++ b/python/ql/test/experimental/CWE-074/Xslt.qlref @@ -0,0 +1 @@ +experimental/CWE-643/Xslt.ql diff --git a/python/ql/test/experimental/CWE-074/XsltSinks.expected b/python/ql/test/experimental/CWE-074/XsltSinks.expected new file mode 100644 index 000000000000..7150b3046e28 --- /dev/null +++ b/python/ql/test/experimental/CWE-074/XsltSinks.expected @@ -0,0 +1,12 @@ +| xslt.py:14:29:14:37 | lxml.etree.parse.xslt | lxml etree xml | +| xsltInjection.py:12:28:12:36 | lxml.etree.XSLT | lxml etree xml | +| xsltInjection.py:21:29:21:37 | lxml.etree.parse.xslt | lxml etree xml | +| xsltInjection.py:31:24:31:32 | lxml.etree.parse.xslt | lxml etree xml | +| xsltInjection.py:40:24:40:32 | lxml.etree.parse.xslt | lxml etree xml | +| xsltInjection.py:50:24:50:32 | lxml.etree.parse.xslt | lxml etree xml | +| xsltInjection.py:60:24:60:32 | lxml.etree.parse.xslt | lxml etree xml | +| xsltInjection.py:69:24:69:32 | lxml.etree.parse.xslt | lxml etree xml | +| xsltInjection.py:79:24:79:32 | lxml.etree.parse.xslt | lxml etree xml | +| xsltSinks.py:17:28:17:36 | lxml.etree.XSLT | lxml etree xml | +| xsltSinks.py:30:29:30:37 | lxml.etree.parse.xslt | lxml etree xml | +| xsltSinks.py:44:24:44:32 | lxml.etree.parse.xslt | lxml etree xml | diff --git a/python/ql/test/experimental/CWE-074/XsltSinks.ql b/python/ql/test/experimental/CWE-074/XsltSinks.ql new file mode 100644 index 000000000000..2149e6921d0b --- /dev/null +++ b/python/ql/test/experimental/CWE-074/XsltSinks.ql @@ -0,0 +1,6 @@ +import python +import experimental.semmle.python.security.injection.XSLT + +from XSLTInjection::XSLTInjectionSink sink, TaintKind kind +where sink.sinks(kind) +select sink, kind diff --git a/python/ql/test/experimental/CWE-074/options b/python/ql/test/experimental/CWE-074/options new file mode 100644 index 000000000000..79d9dcd31b66 --- /dev/null +++ b/python/ql/test/experimental/CWE-074/options @@ -0,0 +1 @@ +semmle-extractor-options: -p ../../query-tests/Security/lib/ --max-import-depth=3 diff --git a/python/ql/test/experimental/CWE-074/xslt.py b/python/ql/test/experimental/CWE-074/xslt.py new file mode 100644 index 000000000000..1655916c7e06 --- /dev/null +++ b/python/ql/test/experimental/CWE-074/xslt.py @@ -0,0 +1,14 @@ +from lxml import etree +from io import StringIO +from flask import Flask, request + +app = Flask(__name__) + + +@app.route("/xslt") +def bad(): + xsltQuery = request.args.get('xml', '') + xslt_root = etree.XML(xsltQuery) + f = StringIO('') + tree = etree.parse(f) + result_tree = tree.xslt(xslt_root) # Not OK diff --git a/python/ql/test/experimental/CWE-074/xsltInjection.py b/python/ql/test/experimental/CWE-074/xsltInjection.py new file mode 100644 index 000000000000..ddab954bbff8 --- /dev/null +++ b/python/ql/test/experimental/CWE-074/xsltInjection.py @@ -0,0 +1,79 @@ +from lxml import etree +from io import StringIO +from flask import Flask, request + +app = Flask(__name__) + + +@app.route("/xslt1") +def a(): + xsltQuery = request.args.get('xml', '') + xslt_root = etree.XML(xsltQuery) + transform = etree.XSLT(xslt_root) # Not OK + + +@app.route("/xslt2") +def b(): + xsltQuery = request.args.get('xml', '') + xslt_root = etree.XML(xsltQuery) + f = StringIO('') + tree = etree.parse(f) + result_tree = tree.xslt(xslt_root) # Not OK + + +@app.route("/xslt3") +def c(): + xsltQuery = request.args.get('xml', '') + xslt_root = etree.XML(xsltQuery) + + f = StringIO('') + tree = etree.parse(f) + result = tree.xslt(xslt_root, a="'A'") # Not OK + +@app.route("/xslt4") +def d(): + xsltQuery = request.args.get('xml', '') + xslt_root = etree.fromstring(xsltQuery) + + f = StringIO('') + tree = etree.parse(f) + result = tree.xslt(xslt_root, a="'A'") # Not OK + +@app.route("/xslt5") +def e(): + xsltQuery = request.args.get('xml', '') + xsltStrings = [xsltQuery,"asd","random"] + xslt_root = etree.fromstringlist(xsltStrings) + + f = StringIO('') + tree = etree.parse(f) + result = tree.xslt(xslt_root, a="'A'") # Not OK + + +@app.route("/xslt6") +def f(): + xsltQuery = '' + xslt_root = etree.XML(xsltQuery) + + f = StringIO('') + tree = etree.parse(f) + result = tree.xslt(xslt_root, a="'A'") # OK + +@app.route("/xslt7") +def g(): + xsltQuery = '' + xslt_root = etree.fromstring(xsltQuery) + + f = StringIO('') + tree = etree.parse(f) + result = tree.xslt(xslt_root, a="'A'") # OK + +@app.route("/xslt8") +def h(): + xsltQuery = '' + xsltStrings = [xsltQuery,"asd","random"] + xslt_root = etree.fromstringlist(xsltStrings) + + f = StringIO('') + tree = etree.parse(f) + result = tree.xslt(xslt_root, a="'A'") # OK \ No newline at end of file diff --git a/python/ql/test/experimental/CWE-074/xsltSinks.py b/python/ql/test/experimental/CWE-074/xsltSinks.py new file mode 100644 index 000000000000..a82fc0c6c5fc --- /dev/null +++ b/python/ql/test/experimental/CWE-074/xsltSinks.py @@ -0,0 +1,56 @@ +from lxml import etree +from io import StringIO + +from django.urls import path +from django.http import HttpResponse +from django.template import Template, Context, Engine, engines + + +def a(request): + xslt_root = etree.XML('''\ + + + + + ''') + transform = etree.XSLT(xslt_root) + + +def b(request): + xslt_root = etree.XML('''\ + + + + + ''') + f = StringIO('') + tree = etree.parse(f) + result_tree = tree.xslt(xslt_root) + + +def c(request): + xslt_root = etree.XML('''\ + + + + + ''') + + f = StringIO('') + tree = etree.parse(f) + result = tree.xslt(xslt_root, a="'A'") + + +urlpatterns = [ + path('a', a), + path('b', b), + path('c', c) +] + +if __name__ == "__main__": + a(None) + b(None) + c(None) diff --git a/python/ql/test/query-tests/Security/lib/lxml/__init__.py b/python/ql/test/query-tests/Security/lib/lxml/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/ql/test/query-tests/Security/lib/lxml/etree.py b/python/ql/test/query-tests/Security/lib/lxml/etree.py new file mode 100644 index 000000000000..b50046ba6f7c --- /dev/null +++ b/python/ql/test/query-tests/Security/lib/lxml/etree.py @@ -0,0 +1,37 @@ +class _ElementTree(object): + def xpath(self, _path, namespaces=None, extensions=None, smart_strings=True, **_variables): + pass + + def xslt(self, _xslt, extensions=None, access_control=None, **_kw): + pass + + +class ETXPath(object): + def __init__(self, path, extensions=None, regexp=True, smart_strings=True): + pass + + +class Xpath(object): + def __init__(self, path, namespaces=None, extensions=None, regexp=True, smart_strings=True): + pass + + +class XSLT(object): + def __init__(self, xslt_input, extensions=None, regexp=True, access_control=None): + pass + + +def parse(self, parser=None, base_url=None): + return _ElementTree() + + +def fromstring(self, text, parser=None, base_url=None): + pass + + +def fromstringlist(self, strings, parser=None): + pass + + +def XML(self, text, parser=None, base_url=None): + pass From 6dd9106301dcb23b6c7d3ed62e78d2819c548f21 Mon Sep 17 00:00:00 2001 From: porcupineyhairs <61983466+porcupineyhairs@users.noreply.github.com> Date: Mon, 8 Jun 2020 03:12:23 +0530 Subject: [PATCH 2/4] Update XSLT.qll --- .../src/experimental/semmle/python/security/injection/XSLT.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/experimental/semmle/python/security/injection/XSLT.qll b/python/ql/src/experimental/semmle/python/security/injection/XSLT.qll index 795d439d83a4..a0680f91de33 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/XSLT.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/XSLT.qll @@ -7,7 +7,7 @@ */ import python -import semmle.python.security.TaintTracking +import semmle.python.dataflow.TaintTracking import semmle.python.web.HttpRequest /** Models XSLT Injection related classes and functions */ From 33a9fb6034b3a58bc273abe926d5f30d9667d12b Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 11 Jun 2020 11:30:54 +0200 Subject: [PATCH 3/4] Python: Reorder XSLT qhelp to be valid --- python/ql/src/experimental/CWE-643/Xslt.qhelp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python/ql/src/experimental/CWE-643/Xslt.qhelp b/python/ql/src/experimental/CWE-643/Xslt.qhelp index cdcc7e4dada5..a3eb44f03c35 100644 --- a/python/ql/src/experimental/CWE-643/Xslt.qhelp +++ b/python/ql/src/experimental/CWE-643/Xslt.qhelp @@ -8,9 +8,9 @@ This vulnerability can be prevented by not allowing untrusted user input to be passed as a XSL stylesheet. If the application logic necessiates processing untrusted XSL stylesheets, the input should be properly filtered and sanitized before use.

- -

In the example below, the XSL stylesheet is controlled by the user and hence leads to a vulnerability.

- -
- \ No newline at end of file + +

In the example below, the XSL stylesheet is controlled by the user and hence leads to a vulnerability.

+ +
+ From a24974b1946ab8e1ed72b02622f460b51d988173 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 11 Jun 2020 11:45:38 +0200 Subject: [PATCH 4/4] Python: Add missing

to qhelp --- python/ql/src/experimental/CWE-643/Xslt.qhelp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/ql/src/experimental/CWE-643/Xslt.qhelp b/python/ql/src/experimental/CWE-643/Xslt.qhelp index a3eb44f03c35..d82dd8ab2c64 100644 --- a/python/ql/src/experimental/CWE-643/Xslt.qhelp +++ b/python/ql/src/experimental/CWE-643/Xslt.qhelp @@ -1,7 +1,9 @@ - Processing an unvalidated XSL stylesheet can allow an attacker to change the structure and contents of the resultant XML, include arbitrary files from the file system, or execute arbitrary code. +

+ Processing an unvalidated XSL stylesheet can allow an attacker to change the structure and contents of the resultant XML, include arbitrary files from the file system, or execute arbitrary code. +