-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathB.java
More file actions
220 lines (187 loc) · 6.19 KB
/
B.java
File metadata and controls
220 lines (187 loc) · 6.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.util.StringTokenizer;
public class B {
public static String[] taint() { return new String[] { "tainted" }; }
public static void sink(Object o) { }
public static void maintest() throws java.io.UnsupportedEncodingException, java.net.MalformedURLException, java.io.IOException {
String[] args = taint();
// tainted - access to main args
String[] aaaargs = args;
sink(aaaargs);
// tainted - access to tainted array
String s = args[0];
sink(s);
// tainted - concatenation of tainted string
String concat = "Look at me " + s + ", I'm tainted!";
sink(concat);
// tainted - parenthesised
String pars = (concat);
sink(pars);
// tainted method argument, implies tainted return value
String method = tainty(pars);
sink(method);
// tainted - complex
String complex = ("Look at me " + args[0]) + ", I'm tainted!";
sink(complex);
// tainted - data preserving constructors
String constructed = new String(complex);
sink(constructed);
// tainted - data preserving method
String valueOf = String.valueOf(complex.toCharArray());
sink(valueOf);
// tainted - data preserving method
String valueOfSubstring = String.valueOf(complex.toCharArray(), 0, 1);
sink(valueOfSubstring);
// tainted - unsafe escape
String badEscape = constructed.replaceAll("irrelevant", "irrelevant");
sink(badEscape);
// tainted - tokenized string
String token = new StringTokenizer(badEscape).nextToken();
sink(token);
// tainted - fluent concatenation
String fluentConcat = "".concat("str").concat(token).concat("bar");
sink(fluentConcat);
// not tainted
String safe = notTainty(complex);
sink(safe);
String shouldBeFine = taintyOtherArg(safe, complex);
sink(shouldBeFine);
// non-whitelisted constructors don't pass taint
StringWrapper herring = new StringWrapper(complex);
sink(herring);
// toString does not pass taint yet
String valueOfObject = String.valueOf(args);
sink(valueOfObject);
// tainted equality check with constant
boolean cond = "foo" == s;
sink(cond);
// tainted logic with tainted operand
boolean logic = cond && safe();
sink(logic);
// tainted
logic = safe() || cond;
sink(logic);
// tainted, use of equals
logic = badEscape.equals("constant");
sink(logic);
// not tainted
boolean okay = s == shouldBeFine;
sink(okay);
// methods on string that pass on taint
String trimmed = s.trim();
sink(trimmed);
String[] split = s.split(" ");
sink(split);
String lower = s.toLowerCase();
sink(lower);
String upper = s.toUpperCase();
sink(upper);
byte[] bytes = s.getBytes("UTF-8");
sink(bytes);
String toString = s.toString();
sink(toString);
String subs = s.substring(1, 10);
sink(subs);
String repl = "some constant".replace(" ", s);
sink(repl);
String replAll = "some constant".replaceAll(" ", s);
sink(replAll);
String replFirst = "some constant".replaceFirst(" ", s);
sink(replFirst);
char[] chars = new char[10];
s.getChars(0, 1, chars, 0);
sink(chars);
String translated = s.translateEscapes();
sink(translated);
ByteArrayOutputStream baos = null;
ObjectOutput oos = null;
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try
{
// serialization of tainted string
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(s);
byte[] serializedData = baos.toByteArray(); // tainted
sink(serializedData);
// serialization of fixed string
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject("not tainted");
byte[] serializedData2 = baos.toByteArray(); // *not* tainted
sink(serializedData2);
// de-serialization of tainted string
bais = new ByteArrayInputStream(serializedData);
ois = new ObjectInputStream(bais);
String deserializedData = (String)ois.readObject(); // tainted
sink(deserializedData);
} catch (IOException e) {
// ignored in test code
} catch (ClassNotFoundException e) {
// ignored in test code
}
// tainted array initializers
String[] taintedArray = new String[] { s };
sink(taintedArray);
String[][] taintedArray2 = new String[][] { { s } };
sink(taintedArray2);
String[][][] taintedArray3 = new String[][][] { { { s } } };
sink(taintedArray3);
// Tainted file path and URI
sink(new java.io.File(s).toURI().toURL());
// Tainted file to Path
sink(new java.io.File(s).toPath());
// Tainted File to Path to File
sink(new java.io.File(s).toPath().toFile());
// Tainted file to absolute file
sink(new java.io.File(s).getAbsoluteFile());
// Tainted file to canonical file
sink(new java.io.File(s).getCanonicalFile());
return;
}
public static String tainty(String arg) {
// tainted return value
return arg;
}
public static String taintyOtherArg(String safe, String tainted) {
return safe;
}
public static String notTainty(String arg) {
return "foo";
}
public static class StringWrapper {
public String wrapped;
public StringWrapper(String s) {
this.wrapped = s;
}
}
public static boolean safe() {
return true;
}
public static void extendedTests(){
String s = taint()[0];
String replReceiver = s.replace("irrelevant", "irrelevant");
sink(replReceiver);
String replChar = "a".replace('a', s.charAt(0));
sink(replChar);
String replCharReceiver = s.replace('a', 'b');
sink(replCharReceiver);
String charAt = "";
for(int i = 0; i < 10; i++)
charAt = charAt + s.charAt(i);
sink(charAt);
byte[] bytes = new byte[10];
s.getBytes(0, 1, bytes, 0);
sink(bytes);
String replAll = s.replaceAll("irrelevant", "irrelevant");
sink(replAll);
String replFirst = s.replaceFirst("irrelevant", "irrelevant");
sink(replFirst);
}
}