Skip to content

Commit 14ce049

Browse files
committed
Add support for Saxon
1 parent d590f3f commit 14ce049

File tree

20 files changed

+328
-45
lines changed

20 files changed

+328
-45
lines changed

java/ql/src/experimental/Security/CWE/CWE-074/XsltInjectionLib.qll

Lines changed: 113 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ class XsltInjectionFlowConfig extends TaintTracking::Configuration {
2424
documentBuilderStep(node1, node2) or
2525
domSourceStep(node1, node2) or
2626
newTransformerOrTemplatesStep(node1, node2) or
27-
newTransformerFromTemplatesStep(node1, node2)
27+
newTransformerFromTemplatesStep(node1, node2) or
28+
xsltCompilerStep(node1, node2) or
29+
xsltExecutableStep(node1, node2) or
30+
xsltPackageStep(node1, node2)
2831
}
2932
}
3033

@@ -43,12 +46,71 @@ class TypeTemplates extends Interface {
4346
TypeTemplates() { this.hasQualifiedName("javax.xml.transform", "Templates") }
4447
}
4548

49+
/** The method `net.sf.saxon.s9api.XsltTransformer.transform`. */
50+
class XsltTransformerTransformMethod extends Method {
51+
XsltTransformerTransformMethod() {
52+
this.getDeclaringType().hasQualifiedName("net.sf.saxon.s9api", "XsltTransformer") and
53+
this.hasName("transform")
54+
}
55+
}
56+
57+
/** The method `net.sf.saxon.s9api.Xslt30Transformer.transform`. */
58+
class Xslt30TransformerTransformMethod extends Method {
59+
Xslt30TransformerTransformMethod() {
60+
this.getDeclaringType().hasQualifiedName("net.sf.saxon.s9api", "Xslt30Transformer") and
61+
this.hasName("transform")
62+
}
63+
}
64+
65+
/** The method `net.sf.saxon.s9api.Xslt30Transformer.applyTemplates`. */
66+
class Xslt30TransformerApplyTemplatesMethod extends Method {
67+
Xslt30TransformerApplyTemplatesMethod() {
68+
this.getDeclaringType().hasQualifiedName("net.sf.saxon.s9api", "Xslt30Transformer") and
69+
this.hasName("applyTemplates")
70+
}
71+
}
72+
73+
/** The method `net.sf.saxon.s9api.Xslt30Transformer.callFunction`. */
74+
class Xslt30TransformerCallFunctionMethod extends Method {
75+
Xslt30TransformerCallFunctionMethod() {
76+
this.getDeclaringType().hasQualifiedName("net.sf.saxon.s9api", "Xslt30Transformer") and
77+
this.hasName("callFunction")
78+
}
79+
}
80+
81+
/** The method `net.sf.saxon.s9api.Xslt30Transformer.callTemplate`. */
82+
class Xslt30TransformerCallTemplateMethod extends Method {
83+
Xslt30TransformerCallTemplateMethod() {
84+
this.getDeclaringType().hasQualifiedName("net.sf.saxon.s9api", "Xslt30Transformer") and
85+
this.hasName("callTemplate")
86+
}
87+
}
88+
89+
/** The class `net.sf.saxon.s9api.XsltCompiler`. */
90+
class TypeXsltCompiler extends Class {
91+
TypeXsltCompiler() { this.hasQualifiedName("net.sf.saxon.s9api", "XsltCompiler") }
92+
}
93+
94+
/** The class `net.sf.saxon.s9api.XsltExecutable`. */
95+
class TypeXsltExecutable extends Class {
96+
TypeXsltExecutable() { this.hasQualifiedName("net.sf.saxon.s9api", "XsltExecutable") }
97+
}
98+
99+
/** The class `net.sf.saxon.s9api.XsltPackage`. */
100+
class TypeXsltPackage extends Class {
101+
TypeXsltPackage() { this.hasQualifiedName("net.sf.saxon.s9api", "XsltPackage") }
102+
}
103+
46104
/** A data flow sink for unvalidated user input that is used in XSLT transformation. */
47105
class XsltInjectionSink extends DataFlow::ExprNode {
48106
XsltInjectionSink() {
49-
exists(MethodAccess ma |
50-
ma.getQualifier() = this.getExpr() and
51-
ma instanceof TransformerTransform
107+
exists(MethodAccess ma, Method m | m = ma.getMethod() and ma.getQualifier() = this.getExpr() |
108+
ma instanceof TransformerTransform or
109+
m instanceof XsltTransformerTransformMethod or
110+
m instanceof Xslt30TransformerTransformMethod or
111+
m instanceof Xslt30TransformerApplyTemplatesMethod or
112+
m instanceof Xslt30TransformerCallFunctionMethod or
113+
m instanceof Xslt30TransformerCallTemplateMethod
52114
)
53115
}
54116
}
@@ -177,3 +239,50 @@ predicate newTransformerFromTemplatesStep(ExprNode n1, ExprNode n2) {
177239
m.hasName("newTransformer")
178240
)
179241
}
242+
243+
/**
244+
* Holds if `n1` to `n2` is a dataflow step that converts between `Source` or `URI` and
245+
* `XsltExecutable` or `XsltPackage`, i.e. `XsltCompiler.compile(tainted)` or
246+
* `XsltCompiler.loadExecutablePackage(tainted)` or `XsltCompiler.compilePackage(tainted)` or
247+
* `XsltCompiler.loadLibraryPackage(tainted)`.
248+
*/
249+
predicate xsltCompilerStep(ExprNode n1, ExprNode n2) {
250+
exists(MethodAccess ma, Method m | ma.getMethod() = m |
251+
n1.asExpr() = ma.getArgument(0) and
252+
n2.asExpr() = ma and
253+
m.getDeclaringType() instanceof TypeXsltCompiler and
254+
(
255+
m.hasName("compile") or
256+
m.hasName("loadExecutablePackage") or
257+
m.hasName("compilePackage") or
258+
m.hasName("loadLibraryPackage")
259+
)
260+
)
261+
}
262+
263+
/**
264+
* Holds if `n1` to `n2` is a dataflow step that converts between `XsltExecutable` and
265+
* `XsltTransformer` or `Xslt30Transformer`, i.e. `XsltExecutable.load()` or
266+
* `XsltExecutable.load30()`.
267+
*/
268+
predicate xsltExecutableStep(ExprNode n1, ExprNode n2) {
269+
exists(MethodAccess ma, Method m | ma.getMethod() = m |
270+
n1.asExpr() = ma.getQualifier() and
271+
n2.asExpr() = ma and
272+
m.getDeclaringType() instanceof TypeXsltExecutable and
273+
(m.hasName("load") or m.hasName("load30"))
274+
)
275+
}
276+
277+
/**
278+
* Holds if `n1` to `n2` is a dataflow step that converts between `XsltPackage` and
279+
* `XsltExecutable`, i.e. `XsltPackage.link()`.
280+
*/
281+
predicate xsltPackageStep(ExprNode n1, ExprNode n2) {
282+
exists(MethodAccess ma, Method m | ma.getMethod() = m |
283+
n1.asExpr() = ma.getQualifier() and
284+
n2.asExpr() = ma and
285+
m.getDeclaringType() instanceof TypeXsltPackage and
286+
m.hasName("link")
287+
)
288+
}

0 commit comments

Comments
 (0)