Skip to content

Commit e99cea3

Browse files
Jami CogswellJami Cogswell
authored andcommitted
Java: update UrlPathBarrier to include FollowsBarrierPrefix
1 parent c5a59d6 commit e99cea3

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

java/ql/lib/semmle/code/java/security/UrlForward.qll

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ abstract class UrlForwardBarrier extends DataFlow::Node { }
4141

4242
private class PrimitiveBarrier extends UrlForwardBarrier instanceof SimpleTypeSanitizer { }
4343

44-
/** A barrier for URLs appended to a prefix. */
45-
private class FollowsBarrierPrefix extends UrlForwardBarrier {
44+
private class FollowsBarrierPrefix extends DataFlow::Node {
4645
FollowsBarrierPrefix() { this.asExpr() = any(BarrierPrefix fp).getAnAppendedExpression() }
4746
}
4847

@@ -55,14 +54,16 @@ private class BarrierPrefix extends InterestingPrefix {
5554
override int getOffset() { result = 0 }
5655
}
5756

58-
/** A barrier that protects against path injection vulnerabilities while accounting for URL encoding. */
57+
/**
58+
* A barrier that protects against path injection vulnerabilities while accounting
59+
* for URL encoding and concatenated prefixes.
60+
*/
5961
private class UrlPathBarrier extends UrlForwardBarrier instanceof PathInjectionSanitizer {
6062
UrlPathBarrier() {
61-
this instanceof ExactPathMatchSanitizer
62-
or
63-
this instanceof NoUrlEncodingBarrier
64-
or
65-
this instanceof FullyDecodesUrlBarrier
63+
this instanceof ExactPathMatchSanitizer or
64+
this instanceof NoUrlEncodingBarrier or
65+
this instanceof FullyDecodesUrlBarrier or
66+
this instanceof FollowsBarrierPrefix
6667
}
6768
}
6869

java/ql/test/query-tests/security/CWE-552/UrlForwardTest.java

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,41 @@ public void bad7(String url, HttpServletRequest request, HttpServletResponse res
8585
@GetMapping("/good1")
8686
public void good1(String url, HttpServletRequest request, HttpServletResponse response) {
8787
try {
88-
request.getRequestDispatcher("/index.jsp?token=" + url).forward(request, response);
88+
request.getRequestDispatcher("/index.jsp?token=" + url).forward(request, response); // $ SPURIOUS: hasUrlForward
89+
} catch (ServletException e) {
90+
e.printStackTrace();
91+
} catch (IOException e) {
92+
e.printStackTrace();
93+
}
94+
}
95+
96+
// BAD: appended to a prefix without path sanitization
97+
@GetMapping("/bad8")
98+
public void bad8(String urlPath, HttpServletRequest request, HttpServletResponse response) {
99+
try {
100+
String url = "/pages" + urlPath;
101+
request.getRequestDispatcher(url).forward(request, response); // $ hasUrlForward
102+
} catch (ServletException e) {
103+
e.printStackTrace();
104+
} catch (IOException e) {
105+
e.printStackTrace();
106+
}
107+
}
108+
109+
// GOOD: appended to a prefix with path sanitization
110+
@GetMapping("/good2")
111+
public void good2(String urlPath, HttpServletRequest request, HttpServletResponse response) {
112+
try {
113+
while (urlPath.contains("%")) {
114+
urlPath = URLDecoder.decode(urlPath, "UTF-8");
115+
}
116+
117+
if (!urlPath.contains("..") && !urlPath.startsWith("/WEB-INF")) {
118+
// Note: path injection sanitizer does not account for string concatenation instead of a `startswith` check
119+
String url = "/pages" + urlPath;
120+
request.getRequestDispatcher(url).forward(request, response);
121+
}
122+
89123
} catch (ServletException e) {
90124
e.printStackTrace();
91125
} catch (IOException e) {

0 commit comments

Comments
 (0)