Skip to content

Commit 4797fce

Browse files
committed
Update use cases and qldoc
1 parent 978ef15 commit 4797fce

File tree

2 files changed

+31
-55
lines changed

2 files changed

+31
-55
lines changed

java/ql/src/experimental/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java

Lines changed: 28 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,78 +5,51 @@ public class UnsafeServletRequestDispatch extends HttpServlet {
55
protected void doGet(HttpServletRequest request, HttpServletResponse response)
66
throws ServletException, IOException {
77
{
8-
// GOOD: whitelisted URI
8+
ServletConfig cfg = getServletConfig();
9+
ServletContext sc = cfg.getServletContext();
10+
11+
// GOOD: check for an explicitly permitted URI
12+
String action = request.getParameter("action");
913
if (action.equals("Login")) {
10-
ServletContext sc = cfg.getServletContext();
1114
RequestDispatcher rd = sc.getRequestDispatcher("/Login.jsp");
1215
rd.forward(request, response);
13-
}
14-
}
16+
}
1517

16-
{
17-
// BAD: Request dispatcher constructed from `ServletContext` without input validation
18+
// BAD: no URI validation
1819
String returnURL = request.getParameter("returnURL");
19-
ServletConfig cfg = getServletConfig();
20-
21-
ServletContext sc = cfg.getServletContext();
2220
RequestDispatcher rd = sc.getRequestDispatcher(returnURL);
2321
rd.forward(request, response);
24-
}
2522

26-
{
27-
// BAD: Request dispatcher without path traversal check
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`
2825
String path = request.getParameter("path");
2926

30-
// A sample payload "/pages/welcome.jsp/../WEB-INF/web.xml" can bypass the `startsWith` check
31-
// The payload "/pages/welcome.jsp/../../%57EB-INF/web.xml" can bypass the check as well since RequestDispatcher will decode `%57` as `W`
27+
// BAD: no check for path traversal
3228
if (path.startsWith(BASE_PATH)) {
3329
request.getServletContext().getRequestDispatcher(path).include(request, response);
3430
}
35-
}
36-
}
37-
38-
{
39-
// GOOD: Request dispatcher with path traversal check
40-
String path = request.getParameter("path");
41-
42-
if (path.startsWith(BASE_PATH) && !path.contains("..")) {
43-
request.getServletContext().getRequestDispatcher(path).include(request, response);
44-
}
45-
}
46-
47-
{
48-
// GOOD: Request dispatcher with path normalization
49-
String path = request.getParameter("path");
50-
Path requestedPath = Paths.get(BASE_PATH).resolve(path).normalize();
51-
52-
// /pages/welcome.jsp/../../WEB-INF/web.xml becomes /WEB-INF/web.xml
53-
// /pages/welcome.jsp/../../%57EB-INF/web.xml becomes /%57EB-INF/web.xml
54-
if (requestedPath.startsWith(BASE_PATH)) {
55-
request.getServletContext().getRequestDispatcher(requestedPath.toString()).forward(request, response);
56-
}
57-
}
5831

59-
{
60-
// BAD: Request dispatcher with improper negation check and without url decoding
61-
String path = request.getParameter("path");
62-
Path requestedPath = Paths.get(BASE_PATH).resolve(path).normalize();
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+
}
6336

64-
if (!requestedPath.startsWith("/WEB-INF") && !requestedPath.startsWith("/META-INF")) {
65-
request.getServletContext().getRequestDispatcher(requestedPath.toString()).forward(request, response);
66-
}
67-
}
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+
}
6842

69-
{
70-
// GOOD: Request dispatcher with path traversal check and url decoding
71-
String path = request.getParameter("path");
72-
boolean hasEncoding = path.contains("%");
73-
while (hasEncoding) {
74-
path = URLDecoder.decode(path, "UTF-8");
75-
hasEncoding = path.contains("%");
76-
}
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+
}
7749

78-
if (!path.startsWith("/WEB-INF/") && !path.contains("..")) {
79-
request.getServletContext().getRequestDispatcher(path).include(request, response);
50+
if (!path.startsWith("/WEB-INF/") && !path.contains("..")) {
51+
request.getServletContext().getRequestDispatcher(path).include(request, response);
52+
}
8053
}
8154
}
8255
}

java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
<p>Unsanitized user provided data must not be used to construct the path for URL forwarding. In order to prevent
1515
untrusted URL forwarding, it is recommended to avoid concatenating user input directly into the forwarding URL.
16+
Instead, user input should be checked for path traversal using <code>..</code> sequences or the user input should
17+
be normalized using <code>Path.normalize</code>, any URL encoding should be removed, and user input should be
18+
checked against a permitted URI.
1619
</p>
1720

1821
</recommendation>

0 commit comments

Comments
 (0)