Skip to content

Commit 04d27f2

Browse files
Jami CogswellJami Cogswell
authored andcommitted
Java: adjust prefix barriers
1 parent e99cea3 commit 04d27f2

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

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

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

4242
private class PrimitiveBarrier extends UrlForwardBarrier instanceof SimpleTypeSanitizer { }
4343

44-
private class FollowsBarrierPrefix extends DataFlow::Node {
44+
/**
45+
* A barrier for values appended to a "redirect:" prefix.
46+
* These results are excluded because they should be handled
47+
* by the `java/unvalidated-url-redirection` query instead.
48+
*/
49+
private class RedirectPrefixBarrier extends UrlForwardBarrier {
50+
RedirectPrefixBarrier() { this.asExpr() = any(RedirectPrefix fp).getAnAppendedExpression() }
51+
}
52+
53+
private class RedirectPrefix extends InterestingPrefix {
54+
RedirectPrefix() { this.getStringValue() = "redirect:" }
55+
56+
override int getOffset() { result = 0 }
57+
}
58+
59+
/**
60+
* A value that is the result of prepending a string that prevents
61+
* any value from controlling the path of a URL.
62+
*/
63+
private class FollowsBarrierPrefix extends UrlForwardBarrier {
4564
FollowsBarrierPrefix() { this.asExpr() = any(BarrierPrefix fp).getAnAppendedExpression() }
4665
}
4766

4867
private class BarrierPrefix extends InterestingPrefix {
68+
int offset;
69+
4970
BarrierPrefix() {
50-
not this.getStringValue().matches("/WEB-INF/%") and
51-
not this instanceof ForwardPrefix
71+
// Matches strings that look like when prepended to untrusted input, they will restrict
72+
// the path of a URL: for example, anything containing `?` or `#`.
73+
exists(this.getStringValue().regexpFind("[?#]", 0, offset))
5274
}
5375

54-
override int getOffset() { result = 0 }
76+
override int getOffset() { result = offset }
5577
}
5678

5779
/**
58-
* A barrier that protects against path injection vulnerabilities while accounting
59-
* for URL encoding and concatenated prefixes.
80+
* A barrier that protects against path injection vulnerabilities
81+
* while accounting for URL encoding.
6082
*/
6183
private class UrlPathBarrier extends UrlForwardBarrier instanceof PathInjectionSanitizer {
6284
UrlPathBarrier() {
6385
this instanceof ExactPathMatchSanitizer or
6486
this instanceof NoUrlEncodingBarrier or
65-
this instanceof FullyDecodesUrlBarrier or
66-
this instanceof FollowsBarrierPrefix
87+
this instanceof FullyDecodesUrlBarrier
6788
}
6889
}
6990

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ public ModelAndView bad4(String url) {
4848
return modelAndView;
4949
}
5050

51+
// Not relevant for this query since redirecting instead of forwarding
52+
// This result should be found by the `java/unvalidated-url-redirection` query instead.
53+
@GetMapping("/redirect")
54+
public ModelAndView redirect(String url) {
55+
ModelAndView modelAndView = new ModelAndView("redirect:" + url);
56+
return modelAndView;
57+
}
58+
5159
// `RequestDispatcher` test cases from a Spring `GetMapping` entry point
5260
@GetMapping("/bad5")
5361
public void bad5(String url, HttpServletRequest request, HttpServletResponse response) {
@@ -85,7 +93,7 @@ public void bad7(String url, HttpServletRequest request, HttpServletResponse res
8593
@GetMapping("/good1")
8694
public void good1(String url, HttpServletRequest request, HttpServletResponse response) {
8795
try {
88-
request.getRequestDispatcher("/index.jsp?token=" + url).forward(request, response); // $ SPURIOUS: hasUrlForward
96+
request.getRequestDispatcher("/index.jsp?token=" + url).forward(request, response);
8997
} catch (ServletException e) {
9098
e.printStackTrace();
9199
} catch (IOException e) {

0 commit comments

Comments
 (0)