Skip to content

Commit 388f60f

Browse files
Merge pull request #4430 from joefarebrother/tainttrackingutils-refactor
Java: Refactor part of TaintTrackingUtil.qll
2 parents b05cc2e + b2a2412 commit 388f60f

File tree

10 files changed

+348
-247
lines changed

10 files changed

+348
-247
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/**
2+
* Provides classes representing various flow steps for taint tracking.
3+
*/
4+
5+
private import java
6+
private import semmle.code.java.dataflow.DataFlow
7+
8+
/**
9+
* A module importing the frameworks that implement additional flow steps,
10+
* ensuring that they are visible to the taint tracking library.
11+
*/
12+
module Frameworks {
13+
private import semmle.code.java.frameworks.jackson.JacksonSerializability
14+
private import semmle.code.java.frameworks.android.Intent
15+
private import semmle.code.java.frameworks.android.SQLite
16+
private import semmle.code.java.frameworks.Guice
17+
private import semmle.code.java.frameworks.Protobuf
18+
}
19+
20+
/**
21+
* A unit class for adding additional taint steps.
22+
*
23+
* Extend this class to add additional taint steps that should apply to all
24+
* taint configurations.
25+
*/
26+
class AdditionalTaintStep extends Unit {
27+
/**
28+
* Holds if the step from `node1` to `node2` should be considered a taint
29+
* step for all configurations.
30+
*/
31+
abstract predicate step(DataFlow::Node node1, DataFlow::Node node2);
32+
}
33+
34+
/**
35+
* A method or constructor that preserves taint.
36+
*
37+
* Extend this class and override at least one of `returnsTaintFrom` or `transfersTaint`
38+
* to add additional taint steps through a method that should apply to all taint configurations.
39+
*/
40+
abstract class TaintPreservingCallable extends Callable {
41+
/**
42+
* Holds if this callable returns tainted data when `arg` tainted.
43+
* `arg` is a parameter index, or is -1 to indicate the qualifier.
44+
*/
45+
predicate returnsTaintFrom(int arg) { none() }
46+
47+
/**
48+
* Holds if this callable writes tainted data to `sink` when `src` is tainted.
49+
* `src` and `sink` are parameter indices, or -1 to indicate the qualifier.
50+
*/
51+
predicate transfersTaint(int src, int sink) { none() }
52+
}
53+
54+
private class StringTaintPreservingMethod extends TaintPreservingCallable {
55+
StringTaintPreservingMethod() {
56+
this.getDeclaringType() instanceof TypeString and
57+
this
58+
.hasName(["concat", "copyValueOf", "endsWith", "format", "formatted", "getBytes", "indent",
59+
"intern", "join", "repeat", "split", "strip", "stripIndent", "stripLeading",
60+
"stripTrailing", "substring", "toCharArray", "toLowerCase", "toString", "toUpperCase",
61+
"trim"])
62+
}
63+
64+
override predicate returnsTaintFrom(int arg) {
65+
arg = -1 and not this.isStatic()
66+
or
67+
this.hasName(["concat", "copyValueOf"]) and arg = 0
68+
or
69+
this.hasName(["format", "formatted", "join"]) and arg = [0 .. getNumberOfParameters()]
70+
}
71+
}
72+
73+
private class StringTaintPreservingConstructor extends Constructor, TaintPreservingCallable {
74+
StringTaintPreservingConstructor() { this.getDeclaringType() instanceof TypeString }
75+
76+
override predicate returnsTaintFrom(int arg) { arg = 0 }
77+
}
78+
79+
private class NumberTaintPreservingCallable extends TaintPreservingCallable {
80+
int argument;
81+
82+
NumberTaintPreservingCallable() {
83+
this.getDeclaringType().getASupertype*().hasQualifiedName("java.lang", "Number") and
84+
(
85+
this instanceof Constructor and
86+
argument = 0
87+
or
88+
this.getName().matches(["to%String", "toByteArray", "%Value"]) and
89+
argument = -1
90+
or
91+
this.getName().matches(["parse%", "valueOf%", "to%String", "decode"]) and
92+
argument = 0
93+
)
94+
}
95+
96+
override predicate returnsTaintFrom(int arg) { arg = argument }
97+
}
98+
99+
/** Holds for the types `StringBuilder`, `StringBuffer`, and `StringWriter`. */
100+
private predicate stringBuilderType(RefType t) {
101+
t.hasQualifiedName("java.lang", "StringBuilder") or
102+
t.hasQualifiedName("java.lang", "StringBuffer") or
103+
t.hasQualifiedName("java.io", "StringWriter")
104+
}
105+
106+
private class StringBuilderTaintPreservingCallable extends TaintPreservingCallable {
107+
StringBuilderTaintPreservingCallable() {
108+
exists(Method m |
109+
this.(Method).overrides*(m) and
110+
stringBuilderType(m.getDeclaringType()) and
111+
m.hasName(["append", "insert", "replace", "toString", "write"])
112+
)
113+
or
114+
this.(Constructor).getParameterType(0) instanceof RefType and
115+
stringBuilderType(this.getDeclaringType())
116+
}
117+
118+
override predicate returnsTaintFrom(int arg) {
119+
arg = -1 and
120+
not this instanceof Constructor
121+
or
122+
this instanceof Constructor and arg = 0
123+
or
124+
this.hasName("append") and arg = 0
125+
or
126+
this.hasName("insert") and arg = 1
127+
or
128+
this.hasName("replace") and arg = 2
129+
}
130+
131+
override predicate transfersTaint(int src, int sink) {
132+
returnsTaintFrom(src) and
133+
sink = -1 and
134+
src != -1 and
135+
not this instanceof Constructor
136+
or
137+
this.hasName("write") and
138+
src = 0 and
139+
sink = -1
140+
}
141+
}

0 commit comments

Comments
 (0)