@@ -112,8 +112,9 @@ public void doFilter2(ServletRequest request, ServletResponse response, FilterCh
112
112
throws IOException , ServletException {
113
113
String path = ((HttpServletRequest ) request ).getServletPath ();
114
114
115
+ // actually BAD since could potentially bypass with ".." encoded as "%2e%2e"?
115
116
if (path .startsWith (BASE_PATH ) && !path .contains (".." )) {
116
- request .getRequestDispatcher (path ).forward (request , response );
117
+ request .getRequestDispatcher (path ).forward (request , response ); // $ hasUrlForward
117
118
} else {
118
119
chain .doFilter (request , response );
119
120
}
@@ -124,6 +125,7 @@ public void doFilter3(ServletRequest request, ServletResponse response, FilterCh
124
125
throws IOException , ServletException {
125
126
String path = ((HttpServletRequest ) request ).getServletPath ();
126
127
128
+ // this is still good, should not flag here..., url-decoding first doesn't matter if looking for exact match... :(
127
129
if (path .equals ("/comaction" )) {
128
130
request .getRequestDispatcher (path ).forward (request , response );
129
131
} else {
@@ -199,8 +201,9 @@ protected void doHead3(HttpServletRequest request, HttpServletResponse response)
199
201
throws ServletException , IOException {
200
202
String path = request .getParameter ("path" );
201
203
204
+ // actually BAD since could potentially bypass with ".." encoded as "%2e%2e"?
202
205
if (path .startsWith (BASE_PATH ) && !path .contains (".." )) {
203
- request .getServletContext ().getRequestDispatcher (path ).include (request , response );
206
+ request .getServletContext ().getRequestDispatcher (path ).include (request , response ); // $ hasUrlForward
204
207
}
205
208
}
206
209
@@ -212,45 +215,151 @@ protected void doHead4(HttpServletRequest request, HttpServletResponse response)
212
215
213
216
// /pages/welcome.jsp/../../WEB-INF/web.xml becomes /WEB-INF/web.xml
214
217
// /pages/welcome.jsp/../../%57EB-INF/web.xml becomes /%57EB-INF/web.xml
218
+ // actually BAD since could potentially bypass with ".." encoded as "%2e%2e": "/pages/welcome.jsp/%2e%2e/%2e%2e/WEB-INF/web.xml" becomes /pages/welcome.jsp/%2e%2e/%2e%2e/WEB-INF/web.xml, which will pass this check and potentially be problematic if decoded later?
215
219
if (requestedPath .startsWith (BASE_PATH )) {
216
- request .getServletContext ().getRequestDispatcher (requestedPath .toString ()).forward (request , response );
220
+ request .getServletContext ().getRequestDispatcher (requestedPath .toString ()).forward (request , response ); // $ hasUrlForward
217
221
}
218
222
}
219
223
220
- // FN: Request dispatcher with negation check and path normalization, but without URL decoding
221
- // When promoting this query, consider using FlowStates to make `getRequestDispatcher` a sink
222
- // only if a URL-decoding step has NOT been crossed (i.e. make URLDecoder.decode change the
223
- // state to a different value than the one required at the sink).
224
- // TODO: but does this need to take into account URLDecoder.decode in a loop...?
224
+ // BAD (original FN): Request dispatcher with negation check and path normalization, but without URL decoding
225
225
protected void doHead5 (HttpServletRequest request , HttpServletResponse response )
226
226
throws ServletException , IOException {
227
227
String path = request .getParameter ("path" );
228
228
Path requestedPath = Paths .get (BASE_PATH ).resolve (path ).normalize ();
229
229
230
230
if (!requestedPath .startsWith ("/WEB-INF" ) && !requestedPath .startsWith ("/META-INF" )) {
231
- request .getServletContext ().getRequestDispatcher (requestedPath .toString ()).forward (request , response ); // $ MISSING: hasUrlForward
231
+ request .getServletContext ().getRequestDispatcher (requestedPath .toString ()).forward (request , response ); // $ hasUrlForward
232
232
}
233
233
}
234
234
235
- // GOOD : Request dispatcher with path traversal check and URL decoding
236
- protected void doHead6 (HttpServletRequest request , HttpServletResponse response )
235
+ // BAD (I added to test decode with no loop) : Request dispatcher with path traversal check and single URL decoding; may be vulnerable to double-encoding
236
+ protected void doHead7 (HttpServletRequest request , HttpServletResponse response )
237
237
throws ServletException , IOException {
238
238
String path = request .getParameter ("path" );
239
+ path = URLDecoder .decode (path , "UTF-8" );
240
+
241
+ if (!path .startsWith ("/WEB-INF/" ) && !path .contains (".." )) {
242
+ request .getServletContext ().getRequestDispatcher (path ).include (request , response ); // $ hasUrlForward
243
+ }
244
+ }
245
+
246
+ // GOOD: Request dispatcher with path traversal check and URL decoding in a loop to avoid double-encoding bypass
247
+ protected void doHead6 (HttpServletRequest request , HttpServletResponse response )
248
+ throws ServletException , IOException {
249
+ String path = request .getParameter ("path" ); // v
250
+
251
+ if (path .contains ("%" )){ // v.getAnAccess()
252
+ while (path .contains ("%" )) {
253
+ path = URLDecoder .decode (path , "UTF-8" );
254
+ }
255
+ }
256
+
257
+ if (!path .startsWith ("/WEB-INF/" ) && !path .contains (".." )) {
258
+ request .getServletContext ().getRequestDispatcher (path ).include (request , response );
259
+ }
260
+ }
261
+
262
+ // GOOD: Request dispatcher with path traversal check and URL decoding in a loop to avoid double-encoding bypass
263
+ protected void doHead8 (HttpServletRequest request , HttpServletResponse response )
264
+ throws ServletException , IOException {
265
+ String path = request .getParameter ("path" ); // v
266
+ while (path .contains ("%" )) {
267
+ path = URLDecoder .decode (path , "UTF-8" );
268
+ }
269
+
270
+ if (!path .startsWith ("/WEB-INF/" ) && !path .contains (".." )) {
271
+ request .getServletContext ().getRequestDispatcher (path ).include (request , response );
272
+ }
273
+ }
274
+
275
+ // FP now....
276
+ // GOOD: Request dispatcher with path traversal check and URL decoding in a loop to avoid double-encoding bypass
277
+ protected void doHead9 (HttpServletRequest request , HttpServletResponse response )
278
+ throws ServletException , IOException {
279
+ String path = request .getParameter ("path" ); // v
239
280
boolean hasEncoding = path .contains ("%" );
240
281
while (hasEncoding ) {
241
282
path = URLDecoder .decode (path , "UTF-8" );
242
283
hasEncoding = path .contains ("%" );
243
284
}
244
285
245
286
if (!path .startsWith ("/WEB-INF/" ) && !path .contains (".." )) {
246
- request .getServletContext ().getRequestDispatcher (path ).include (request , response );
287
+ request .getServletContext ().getRequestDispatcher (path ).include (request , response ); // $ SPURIOUS: hasUrlForward
247
288
}
248
289
}
249
290
250
- // New Tests (i.e. Added by me)
291
+ // New Tests
251
292
public void generateResponse (StaplerRequest req , StaplerResponse rsp , Object obj ) throws IOException , ServletException {
252
293
String url = req .getParameter ("target" );
253
294
rsp .forward (obj , url , req ); // $ hasUrlForward
254
295
}
255
296
297
+ // Other Tests for edge cases:
298
+ // // GOOD (I added): Request dispatcher with path traversal check and URL decoding in a loop to avoid double-encoding bypass
299
+ // // testing `if` stmt requirement for BB controlling
300
+ // protected void doHead12(HttpServletRequest request, HttpServletResponse response)
301
+ // throws ServletException, IOException {
302
+ // String path = request.getParameter("path");
303
+ // if (path.contains("%")) {
304
+ // while (path.contains("%")) {
305
+ // path = URLDecoder.decode(path, "UTF-8");
306
+ // }
307
+ // }
308
+ // if (!path.startsWith("/WEB-INF/") && !path.contains("..")) {
309
+ // request.getServletContext().getRequestDispatcher(path).include(request, response);
310
+ // }
311
+ // }
312
+ // // BAD (I added): Request dispatcher with path traversal check and single URL decoding; may be vulnerable to double-encoding
313
+ // // Tests urlEncoding BarrierGuard "a guard that considers a string safe because it is checked for URL encoding sequences,
314
+ // // having previously been checked against a block-list of forbidden values."
315
+ // protected void doHead8(HttpServletRequest request, HttpServletResponse response)
316
+ // throws ServletException, IOException {
317
+ // String path = request.getParameter("path");
318
+
319
+ // if (!path.startsWith("/WEB-INF/") && !path.contains("..")) {
320
+ // boolean hasEncoding = path.contains("%"); // BAD: doesn't do anything with the check...
321
+ // request.getServletContext().getRequestDispatcher(path).include(request, response); // $ hasUrlForward
322
+ // }
323
+ // }
324
+ // // BAD (I added): Request dispatcher with path traversal check and single URL decoding; may be vulnerable to double-encoding
325
+ // // Tests urlEncoding BarrierGuard "a guard that considers a string safe because it is checked for URL encoding sequences,
326
+ // // having previously been checked against a block-list of forbidden values."
327
+ // protected void doHead9(HttpServletRequest request, HttpServletResponse response)
328
+ // throws ServletException, IOException {
329
+ // String path = request.getParameter("path");
330
+
331
+ // boolean hasEncoding = path.contains("%"); // BAD: doesn't do anything with the check... and check comes BEFORE blocklist so guard should not trigger
332
+ // if (!path.startsWith("/WEB-INF/") && !path.contains("..")) {
333
+ // request.getServletContext().getRequestDispatcher(path).include(request, response); // $ hasUrlForward
334
+ // }
335
+ // }
336
+
337
+ // // BAD (I added): Request dispatcher with path traversal check and single URL decoding; may be vulnerable to double-encoding
338
+ // // Tests urlEncoding BarrierGuard "a guard that considers a string safe because it is checked for URL encoding sequences,
339
+ // // having previously been checked against a block-list of forbidden values."
340
+ // protected void doHead10(HttpServletRequest request, HttpServletResponse response)
341
+ // throws ServletException, IOException {
342
+ // String path = request.getParameter("path");
343
+
344
+ // if (!path.startsWith("/WEB-INF/") && !path.contains("..")) {
345
+ // if (path.contains("%")){ // BAD: wrong check
346
+ // request.getServletContext().getRequestDispatcher(path).include(request, response); // $ hasUrlForward
347
+ // }
348
+ // }
349
+ // }
350
+
351
+ // // "GOOD" (I added): Request dispatcher with path traversal check and single URL decoding; may be vulnerable to double-encoding
352
+ // // Tests urlEncoding BarrierGuard "a guard that considers a string safe because it is checked for URL encoding sequences,
353
+ // // having previously been checked against a block-list of forbidden values."
354
+ // protected void doHead11(HttpServletRequest request, HttpServletResponse response)
355
+ // throws ServletException, IOException {
356
+ // String path = request.getParameter("path");
357
+
358
+ // if (!path.startsWith("/WEB-INF/") && !path.contains("..")) {
359
+ // if (!path.contains("%")){ // GOOD: right check
360
+ // request.getServletContext().getRequestDispatcher(path).include(request, response);
361
+ // }
362
+ // }
363
+ // }
364
+
256
365
}
0 commit comments