forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathSanitizationTests.java
More file actions
144 lines (116 loc) · 7.75 KB
/
SanitizationTests.java
File metadata and controls
144 lines (116 loc) · 7.75 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
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SanitizationTests extends HttpServlet {
private static final String VALID_URI = "http://lgtm.com";
private HttpClient client = HttpClient.newHttpClient();
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
URI uri = new URI(request.getParameter("uri")); // $ Source
// BAD: a request parameter is incorporated without validation into a Http
// request
HttpRequest r = HttpRequest.newBuilder(uri).build(); // $ Alert
client.send(r, null); // $ Alert
// GOOD: sanitisation by concatenation with a prefix that prevents targeting an arbitrary host.
// We test a few different ways of sanitisation: via string conctentation (perhaps nested),
// via a stringbuilder (for which we consider appends done in the constructor, chained onto
// the constructor and applied in subsequent statements) and via String.format.
String safeUri3 = "https://example.com/" + request.getParameter("uri3");
HttpRequest r3 = HttpRequest.newBuilder(new URI(safeUri3)).build();
client.send(r3, null);
String safeUri4 = "https://example.com/" + ("someprefix" + request.getParameter("uri4"));
HttpRequest r4 = HttpRequest.newBuilder(new URI(safeUri4)).build();
client.send(r4, null);
StringBuilder safeUri5 = new StringBuilder();
safeUri5.append("https://example.com/").append(request.getParameter("uri5"));
HttpRequest r5 = HttpRequest.newBuilder(new URI(safeUri5.toString())).build();
client.send(r5, null);
StringBuilder safeUri5a = new StringBuilder("https://example.com/");
safeUri5a.append(request.getParameter("uri5a"));
HttpRequest r5a = HttpRequest.newBuilder(new URI(safeUri5a.toString())).build();
client.send(r5a, null);
StringBuilder safeUri5b = (new StringBuilder("https://example.com/")).append("dir/");
safeUri5b.append(request.getParameter("uri5b"));
HttpRequest r5b = HttpRequest.newBuilder(new URI(safeUri5b.toString())).build();
client.send(r5b, null);
StringBuilder safeUri5c = (new StringBuilder("prefix")).append("https://example.com/dir/");
safeUri5c.append(request.getParameter("uri5c"));
HttpRequest r5c = HttpRequest.newBuilder(new URI(safeUri5c.toString())).build();
client.send(r5c, null);
String safeUri6 = String.format("https://example.com/%s", request.getParameter("uri6"));
HttpRequest r6 = HttpRequest.newBuilder(new URI(safeUri6)).build();
client.send(r6, null);
String safeUri7 = String.format("%s/%s", "https://example.com", request.getParameter("uri7"));
HttpRequest r7 = HttpRequest.newBuilder(new URI(safeUri7)).build();
client.send(r7, null);
String safeUri8 = String.format("%s%s", "https://example.com/", request.getParameter("uri8"));
HttpRequest r8 = HttpRequest.newBuilder(new URI(safeUri8)).build();
client.send(r8, null);
String safeUri9 = String.format("http://%s", "myserver.com") + "/" + request.getParameter("uri9");
HttpRequest r9 = HttpRequest.newBuilder(new URI(safeUri9)).build();
client.send(r9, null);
// BAD: cases where a string that would sanitise is used, but occurs in the wrong
// place to sanitise user input:
String unsafeUri3 = request.getParameter("baduri3") + "https://example.com/"; // $ Source
HttpRequest unsafer3 = HttpRequest.newBuilder(new URI(unsafeUri3)).build(); // $ Alert
client.send(unsafer3, null); // $ Alert
String unsafeUri4 = ("someprefix" + request.getParameter("baduri4")) + "https://example.com/"; // $ Source
HttpRequest unsafer4 = HttpRequest.newBuilder(new URI(unsafeUri4)).build(); // $ Alert
client.send(unsafer4, null); // $ Alert
StringBuilder unsafeUri5 = new StringBuilder();
unsafeUri5.append(request.getParameter("baduri5")).append("https://example.com/"); // $ Source
HttpRequest unsafer5 = HttpRequest.newBuilder(new URI(unsafeUri5.toString())).build(); // $ Alert
client.send(unsafer5, null); // $ Alert
StringBuilder unafeUri5a = new StringBuilder(request.getParameter("uri5a")); // $ Source
unafeUri5a.append("https://example.com/");
HttpRequest unsafer5a = HttpRequest.newBuilder(new URI(unafeUri5a.toString())).build(); // $ Alert
client.send(unsafer5a, null); // $ Alert
StringBuilder unsafeUri5b = (new StringBuilder(request.getParameter("uri5b"))).append("dir/"); // $ Source
unsafeUri5b.append("https://example.com/");
HttpRequest unsafer5b = HttpRequest.newBuilder(new URI(unsafeUri5b.toString())).build(); // $ Alert
client.send(unsafer5b, null); // $ Alert
StringBuilder unsafeUri5c = (new StringBuilder("https")).append(request.getParameter("uri5c")); // $ Source
unsafeUri5c.append("://example.com/dir/");
HttpRequest unsafer5c = HttpRequest.newBuilder(new URI(unsafeUri5c.toString())).build(); // $ Alert
client.send(unsafer5c, null); // $ Alert
String unsafeUri6 = String.format("%shttps://example.com/", request.getParameter("baduri6")); // $ Source
HttpRequest unsafer6 = HttpRequest.newBuilder(new URI(unsafeUri6)).build(); // $ Alert
client.send(unsafer6, null); // $ Alert
String unsafeUri7 = String.format("%s/%s", request.getParameter("baduri7"), "https://example.com"); // $ Source
HttpRequest unsafer7 = HttpRequest.newBuilder(new URI(unsafeUri7)).build(); // $ Alert
client.send(unsafer7, null); // $ Alert
String unsafeUri8 = String.format("%s%s", request.getParameter("baduri8"), "https://example.com/"); // $ Source
HttpRequest unsafer8 = HttpRequest.newBuilder(new URI(unsafeUri8)).build(); // $ Alert
client.send(unsafer8, null); // $ Alert
String unsafeUri9 = request.getParameter("baduri9") + "/" + String.format("http://%s", "myserver.com"); // $ Source
HttpRequest unsafer9 = HttpRequest.newBuilder(new URI(unsafeUri9)).build(); // $ Alert
client.send(unsafer9, null); // $ Alert
String unsafeUri10 = String.format("%s://%s:%s%s", "http", "myserver.com", "80", request.getParameter("baduri10")); // $ Source
HttpRequest unsafer10 = HttpRequest.newBuilder(new URI(unsafeUri10)).build(); // $ Alert
client.send(unsafer10, null); // $ Alert
// GOOD: sanitisation by regexp validation
String param10 = request.getParameter("uri10");
if (param10.matches("[a-zA-Z0-9_-]+")) {
HttpRequest r10 = HttpRequest.newBuilder(new URI(param10)).build();
client.send(r10, null);
}
String param11 = request.getParameter("uri11");
validate(param11);
HttpRequest r11 = HttpRequest.newBuilder(new URI(param11)).build();
client.send(r11, null);
} catch (Exception e) {
// TODO: handle exception
}
}
private void validate(String s) {
if (!s.matches("[a-zA-Z0-9_-]+")) {
throw new IllegalArgumentException("Invalid ID");
}
}
}