Skip to content

Commit a3d65a8

Browse files
committed
Update recommendation in qldoc and make examples more comprehendible
1 parent 4797fce commit a3d65a8

File tree

3 files changed

+14
-88
lines changed

3 files changed

+14
-88
lines changed

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

Lines changed: 0 additions & 30 deletions
This file was deleted.
Lines changed: 11 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,11 @@
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("%")) { ... }

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +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.
16+
Instead, user input should be checked against allowed (e.g., must come within <code>user_content/</code>) or disallowed
17+
(e.g. must not come within <code>/internal</code>) paths, ensuring that neither path traversal using <code>../</code>
18+
or URL encoding are used to evade these checks.
1919
</p>
2020

2121
</recommendation>

0 commit comments

Comments
 (0)