1
- public class UnsafeServletRequestDispatch extends HttpServlet {
2
- private static final String BASE_PATH = "/pages" ;
3
-
4
- @ Override
5
- protected void doGet (HttpServletRequest request , HttpServletResponse response )
6
- throws ServletException , IOException {
7
- {
8
- ServletConfig cfg = getServletConfig ();
9
- ServletContext sc = cfg .getServletContext ();
10
-
11
- // GOOD: check for an explicitly permitted URI
12
- String action = request .getParameter ("action" );
13
- if (action .equals ("Login" )) {
14
- RequestDispatcher rd = sc .getRequestDispatcher ("/Login.jsp" );
15
- rd .forward (request , response );
16
- }
17
-
18
- // BAD: no URI validation
19
- String returnURL = request .getParameter ("returnURL" );
20
- RequestDispatcher rd = sc .getRequestDispatcher (returnURL );
21
- rd .forward (request , response );
22
-
23
- // A sample payload "/pages/welcome.jsp/../WEB-INF/web.xml" can bypass the `startsWith` check
24
- // The payload "/pages/welcome.jsp/../../%57EB-INF/web.xml" can bypass the check as well since RequestDispatcher will decode `%57` as `W`
25
- String path = request .getParameter ("path" );
26
-
27
- // BAD: no check for path traversal
28
- if (path .startsWith (BASE_PATH )) {
29
- request .getServletContext ().getRequestDispatcher (path ).include (request , response );
30
- }
31
-
32
- // GOOD: To check there won't be unexpected path traversal, we can check for any `..` sequences and whether the URI starts with a given web root path.
33
- if (path .startsWith (BASE_PATH ) && !path .contains (".." )) {
34
- request .getServletContext ().getRequestDispatcher (path ).include (request , response );
35
- }
36
-
37
- // GOOD: Or alternatively we can use Path.normalize and check whether the URI starts with a given web root path.
38
- Path requestedPath = Paths .get (BASE_PATH ).resolve (path ).normalize ();
39
- if (requestedPath .startsWith (BASE_PATH )) {
40
- request .getServletContext ().getRequestDispatcher (requestedPath .toString ()).forward (request , response );
41
- }
42
-
43
- // GOOD: Or alternatively ensure URL encoding is removed and then check for any `..` sequences.
44
- boolean hasEncoding = path .contains ("%" );
45
- while (hasEncoding ) {
46
- path = URLDecoder .decode (path , "UTF-8" );
47
- hasEncoding = path .contains ("%" );
48
- }
49
-
50
- if (!path .startsWith ("/WEB-INF/" ) && !path .contains (".." )) {
51
- request .getServletContext ().getRequestDispatcher (path ).include (request , response );
52
- }
53
- }
54
- }
55
- }
1
+ // BAD: no URI validation
2
+ String returnURL = request .getParameter ("returnURL" );
3
+ RequestDispatcher rd = sc .getRequestDispatcher (returnURL );
4
+ rd .forward (request , response );
5
+
6
+ // GOOD: check for a trusted prefix, ensuring path traversal is not used to erase that prefix:
7
+ // (alternatively use `Path.normalize` instead of checking for `..`)
8
+ if (!returnURL .contains (".." ) && returnURL .hasPrefix ("/pages" )) { ... }
9
+ // Also GOOD: check for a forbidden prefix, ensuring URL-encoding is not used to evade the check:
10
+ // (alternatively use `URLDecoder.decode` before `hasPrefix`)
11
+ if (returnURL .hasPrefix ("/internal" ) && !returnURL .contains ("%" )) { ... }
0 commit comments