@@ -112,8 +112,9 @@ public void doFilter2(ServletRequest request, ServletResponse response, FilterCh
112112 throws IOException , ServletException {
113113 String path = ((HttpServletRequest ) request ).getServletPath ();
114114
115+ // actually BAD since could potentially bypass with ".." encoded as "%2e%2e"?
115116 if (path .startsWith (BASE_PATH ) && !path .contains (".." )) {
116- request .getRequestDispatcher (path ).forward (request , response );
117+ request .getRequestDispatcher (path ).forward (request , response ); // $ hasUrlForward
117118 } else {
118119 chain .doFilter (request , response );
119120 }
@@ -124,6 +125,7 @@ public void doFilter3(ServletRequest request, ServletResponse response, FilterCh
124125 throws IOException , ServletException {
125126 String path = ((HttpServletRequest ) request ).getServletPath ();
126127
128+ // this is still good, should not flag here..., url-decoding first doesn't matter if looking for exact match... :(
127129 if (path .equals ("/comaction" )) {
128130 request .getRequestDispatcher (path ).forward (request , response );
129131 } else {
@@ -199,8 +201,9 @@ protected void doHead3(HttpServletRequest request, HttpServletResponse response)
199201 throws ServletException , IOException {
200202 String path = request .getParameter ("path" );
201203
204+ // actually BAD since could potentially bypass with ".." encoded as "%2e%2e"?
202205 if (path .startsWith (BASE_PATH ) && !path .contains (".." )) {
203- request .getServletContext ().getRequestDispatcher (path ).include (request , response );
206+ request .getServletContext ().getRequestDispatcher (path ).include (request , response ); // $ hasUrlForward
204207 }
205208 }
206209
@@ -212,45 +215,151 @@ protected void doHead4(HttpServletRequest request, HttpServletResponse response)
212215
213216 // /pages/welcome.jsp/../../WEB-INF/web.xml becomes /WEB-INF/web.xml
214217 // /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?
215219 if (requestedPath .startsWith (BASE_PATH )) {
216- request .getServletContext ().getRequestDispatcher (requestedPath .toString ()).forward (request , response );
220+ request .getServletContext ().getRequestDispatcher (requestedPath .toString ()).forward (request , response ); // $ hasUrlForward
217221 }
218222 }
219223
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
225225 protected void doHead5 (HttpServletRequest request , HttpServletResponse response )
226226 throws ServletException , IOException {
227227 String path = request .getParameter ("path" );
228228 Path requestedPath = Paths .get (BASE_PATH ).resolve (path ).normalize ();
229229
230230 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
232232 }
233233 }
234234
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 )
237237 throws ServletException , IOException {
238238 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
239280 boolean hasEncoding = path .contains ("%" );
240281 while (hasEncoding ) {
241282 path = URLDecoder .decode (path , "UTF-8" );
242283 hasEncoding = path .contains ("%" );
243284 }
244285
245286 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
247288 }
248289 }
249290
250- // New Tests (i.e. Added by me)
291+ // New Tests
251292 public void generateResponse (StaplerRequest req , StaplerResponse rsp , Object obj ) throws IOException , ServletException {
252293 String url = req .getParameter ("target" );
253294 rsp .forward (obj , url , req ); // $ hasUrlForward
254295 }
255296
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+
256365}
0 commit comments