Skip to content

Commit 4b491dc

Browse files
committed
Add codehaus sink and taint steps
1 parent 7883549 commit 4b491dc

1 file changed

Lines changed: 57 additions & 3 deletions

File tree

java/ql/src/semmle/code/java/security/GroovyInjection.qll

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,24 @@ private class DefaultLdapInjectionSinkModel extends SinkModelCsv {
3939
"groovy.util;Eval;false;x;(Object,String);;Argument[1];groovy",
4040
"groovy.util;Eval;false;xy;(Object,Object,String);;Argument[2];groovy",
4141
"groovy.util;Eval;false;xyz;(Object,Object,Object,String);;Argument[3];groovy",
42-
"groovy.lang;GroovyClassLoader;false;parseClass;;;Argument[0];groovy"
42+
"groovy.lang;GroovyClassLoader;false;parseClass;;;Argument[0];groovy",
43+
"org.codehaus.groovy.control;CompilationUnit;false;compile;;;Argument[-1];groovy"
4344
]
4445
}
4546
}
4647

4748
/** A set of additional taint steps to consider when taint tracking Groovy related data flows. */
4849
private class DefaultGroovyInjectionAdditionalTaintStep extends GroovyInjectionAdditionalTaintStep {
4950
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
50-
groovyCodeSourceTaintStep(node1, node2)
51+
groovyCodeSourceTaintStep(node1, node2) or
52+
groovyCompilationUnitTaintStep(node1, node2) or
53+
groovySourceUnitTaintStep(node1, node2)
5154
}
5255
}
5356

5457
/**
5558
* Holds if `fromNode` to `toNode` is a dataflow step from a tainted string to
56-
* a `GroovyCodeSource` instance, i.e. `new GroovyCodeSource(tainted, ...)`.
59+
* a `GroovyCodeSource` instance by calling `new GroovyCodeSource(tainted, ...)`.
5760
*/
5861
private predicate groovyCodeSourceTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
5962
exists(ConstructorCall gcscc |
@@ -63,7 +66,58 @@ private predicate groovyCodeSourceTaintStep(DataFlow::Node fromNode, DataFlow::N
6366
)
6467
}
6568

69+
/**
70+
* Holds if `fromNode` to `toNode` is a dataflow step from a tainted string to
71+
* a `CompilationUnit` instance by calling `compilationUnit.addSource(..., tainted)`.
72+
*/
73+
private predicate groovyCompilationUnitTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
74+
exists(MethodAccess ma, Method m |
75+
ma.getMethod() = m and
76+
m.hasName("addSource") and
77+
m.getDeclaringType() instanceof TypeGroovyCompilationUnit
78+
|
79+
fromNode.asExpr() = ma.getArgument(ma.getNumArgument() - 1) and
80+
toNode.asExpr() = ma.getQualifier()
81+
)
82+
}
83+
84+
/**
85+
* Holds if `fromNode` to `toNode` is a dataflow step from a tainted string to
86+
* a `SourceUnit` instance by calling `new SourceUnit(..., tainted, ...)`
87+
* or `SourceUnit.create(..., tainted)`
88+
*/
89+
private predicate groovySourceUnitTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
90+
exists(ClassInstanceExpr cie, Argument arg |
91+
cie.getConstructedType() instanceof TypeGroovySourceUnit and
92+
arg = cie.getArgument(1) and
93+
arg.getType() instanceof TypeString
94+
|
95+
fromNode.asExpr() = arg and
96+
toNode.asExpr() = cie
97+
)
98+
or
99+
exists(MethodAccess ma, Method m |
100+
ma.getMethod() = m and
101+
m.hasName("create") and
102+
m.getDeclaringType() instanceof TypeGroovySourceUnit
103+
|
104+
fromNode.asExpr() = ma.getArgument(1) and toNode.asExpr() = ma
105+
)
106+
}
107+
66108
/** The class `groovy.lang.GroovyCodeSource`. */
67109
private class TypeGroovyCodeSource extends RefType {
68110
TypeGroovyCodeSource() { this.hasQualifiedName("groovy.lang", "GroovyCodeSource") }
69111
}
112+
113+
/** The class `org.codehaus.groovy.control.CompilationUnit`. */
114+
private class TypeGroovyCompilationUnit extends RefType {
115+
TypeGroovyCompilationUnit() {
116+
this.hasQualifiedName("org.codehaus.groovy.control", "CompilationUnit")
117+
}
118+
}
119+
120+
/** The class `org.codehaus.groovy.control.CompilationUnit`. */
121+
private class TypeGroovySourceUnit extends RefType {
122+
TypeGroovySourceUnit() { this.hasQualifiedName("org.codehaus.groovy.control", "SourceUnit") }
123+
}

0 commit comments

Comments
 (0)