-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Java: Treat x.matches(regexp) as a sanitizer for request forgery
#20688
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -164,3 +164,24 @@ private class HostComparisonSanitizer extends RequestForgerySanitizer { | |
| this = DataFlow::BarrierGuard<isHostComparisonSanitizer/3>::getABarrierNode() | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * A qualifier in a call to a `.matches()` method that is a sanitizer for URL redirects. | ||
| * | ||
| * Matches any method call where the method is named `matches`. | ||
| */ | ||
| private predicate isMatchesSanitizer(Guard guard, Expr e, boolean branch) { | ||
| guard = | ||
| any(MethodCall method | | ||
| method.getMethod().getName() = "matches" and | ||
| e = method.getQualifier() and | ||
| branch = true | ||
| ) | ||
| } | ||
|
|
||
| /** | ||
| * A qualifier in a call to `.matches()` that is a sanitizer for URL redirects. | ||
|
||
| */ | ||
| private class MatchesSanitizer extends RequestForgerySanitizer { | ||
| MatchesSanitizer() { this = DataFlow::BarrierGuard<isMatchesSanitizer/3>::getABarrierNode() } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| --- | ||
| category: minorAnalysis | ||
| --- | ||
| * Calls to `String.matches` are now treated as sanitizers for the `java/ssrf` query. |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -119,8 +119,30 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) | |||||
| String unsafeUri10 = String.format("%s://%s:%s%s", "http", "myserver.com", "80", request.getParameter("baduri10")); // $ Source | ||||||
| HttpRequest unsafer10 = HttpRequest.newBuilder(new URI(unsafeUri10)).build(); // $ Alert | ||||||
| client.send(unsafer10, null); // $ Alert | ||||||
|
|
||||||
| // GOOD: sanitisation by regexp validation | ||||||
| String safeUri10 = "https://example.com/"; | ||||||
| String param10 = request.getParameter("uri10"); | ||||||
| if (param10.matches("[a-zA-Z0-9/_-]+")) { | ||||||
| safeUri10 = safeUri10 + param10; | ||||||
| } | ||||||
| HttpRequest r10 = HttpRequest.newBuilder(new URI(safeUri10)).build(); | ||||||
| client.send(r10, null); | ||||||
|
|
||||||
|
|
||||||
| String param11 = request.getParameter("uri11"); | ||||||
| validate(param11); | ||||||
| String safeUri11 = "https://example.com/" + param11; | ||||||
| HttpRequest r11 = HttpRequest.newBuilder(new URI(safeUri11)).build(); | ||||||
| client.send(r11, null); | ||||||
|
Comment on lines
123
to
133
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wait a minute, are these two test cases even testing the regex sanitizer? If I've understood the existing sanitizers correctly, then the concatenation with a fixed url ending in
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two test cases need to replace the fixed-string url "https://example.com/" with something that isn't analyzable as a potential url-prefix by the StringPrefixes library. Maybe just get the string from a collection field that we pretend is initialized or something.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch; the first test is actually ok, since
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have verified that the updated tests both result in alerts when the sanitizer is disabled. |
||||||
| } catch (Exception e) { | ||||||
| // TODO: handle exception | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| private void validate(String s) { | ||||||
| if (!s.matches("[a-zA-Z0-9/_-]+")) { | ||||||
|
||||||
| if (!s.matches("[a-zA-Z0-9/_-]+")) { | |
| if (!s.matches("[a-zA-Z0-9_-]+")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I happily took what Copilot gave me ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation mentions 'URL redirects' but this sanitizer is for request forgery (SSRF), not URL redirection. The comment should refer to 'request forgery' or 'SSRF' to match the actual usage context.