mirror of
https://github.com/github/codeql.git
synced 2025-12-21 11:16:30 +01:00
Add sinks of servlet dispatcher and filter
This commit is contained in:
@@ -33,6 +33,24 @@ private class GetServletUriSource extends SourceModelCsv {
|
||||
}
|
||||
}
|
||||
|
||||
/** Sink model of servlet dispatcher. */
|
||||
private class UrlDispatchSink extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"javax.servlet;RequestDispatcher;false;forward;;;Argument[-1];url-dispatch;manual",
|
||||
"javax.servlet;RequestDispatcher;false;include;;;Argument[-1];url-dispatch;manual"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/** Sink model of servlet filter. */
|
||||
private class UrlFilterSink extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row = ["javax.servlet;FilterChain;true;doFilter;;;Argument[-1];url-filter;manual"]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* `.` without a `\` prefix, which is likely not a character literal in regex
|
||||
*/
|
||||
@@ -119,7 +137,11 @@ class MatchRegexConfiguration extends TaintTracking::Configuration {
|
||||
DataFlow::localExprFlow(ce, guard.(MethodAccess).getQualifier()) or
|
||||
DataFlow::localExprFlow(ce, guard.(MethodAccess).getAnArgument())
|
||||
) and
|
||||
DataFlow::exprNode(se) instanceof UrlRedirectSink and
|
||||
(
|
||||
DataFlow::exprNode(se) instanceof UrlRedirectSink or
|
||||
sinkNode(DataFlow::exprNode(se), "url-dispatch") or
|
||||
sinkNode(DataFlow::exprNode(se), "url-filter")
|
||||
) and
|
||||
guard.controls(se.getBasicBlock(), true)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class DotRegexFilter implements Filter {
|
||||
private static final String PROTECTED_PATTERN = "/protected/.*";
|
||||
private static final String CONSTRAINT_PATTERN = "/protected/xyz\\.xml";
|
||||
|
||||
private ServletContext context;
|
||||
|
||||
public void init(FilterConfig config) throws ServletException {
|
||||
this.context = config.getServletContext();
|
||||
}
|
||||
|
||||
// BAD: A string with line return e.g. `/protected/%0dxyz` can bypass the path check
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||
String source = httpRequest.getPathInfo();
|
||||
|
||||
Pattern p = Pattern.compile(PROTECTED_PATTERN);
|
||||
Matcher m = p.matcher(source);
|
||||
|
||||
if (m.matches()) {
|
||||
// Protected page - check access token and redirect to login page
|
||||
if (!httpRequest.getSession().getAttribute("secAttr").equals("secValue")) {
|
||||
// Redirect to the login page
|
||||
httpResponse.sendRedirect("/login.html");
|
||||
} else {
|
||||
// Not protected page - pass the request along the filter chain
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: A string with line return e.g. `/protected/%0dxyz` cannot bypass the path check
|
||||
public void doFilter2(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||
String source = httpRequest.getPathInfo();
|
||||
|
||||
Pattern p = Pattern.compile(CONSTRAINT_PATTERN);
|
||||
Matcher m = p.matcher(source);
|
||||
|
||||
if (m.matches()) {
|
||||
// Protected page - check access token and redirect to login page
|
||||
if (!httpRequest.getSession().getAttribute("secAttr").equals("secValue")) {
|
||||
// Redirect to the login page
|
||||
httpResponse.sendRedirect("/login.html");
|
||||
} else {
|
||||
// Not protected page - pass the request along the filter chain
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
// Close resources
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import java.util.regex.Pattern;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
public class DotRegexServlet extends HttpServlet {
|
||||
@@ -104,4 +105,46 @@ public class DotRegexServlet extends HttpServlet {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BAD: A string with line return e.g. `/protected/%0dxyz` can bypass the path check
|
||||
protected void doGet6(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String source = request.getPathInfo();
|
||||
|
||||
Pattern p = Pattern.compile(PROTECTED_PATTERN);
|
||||
Matcher m = p.matcher(source);
|
||||
|
||||
if (m.matches()) {
|
||||
// Protected page - check access token and redirect to login page
|
||||
if (!request.getSession().getAttribute("secAttr").equals("secValue")) {
|
||||
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/login");
|
||||
dispatcher.forward(request, response);
|
||||
} else {
|
||||
// Not protected page - render content
|
||||
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(source);
|
||||
dispatcher.forward(request, response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: A string with line return e.g. `/protected/%0dxyz` cannot bypass the path check
|
||||
protected void doGet7(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String source = request.getPathInfo();
|
||||
|
||||
Pattern p = Pattern.compile(PROTECTED_PATTERN, Pattern.DOTALL);
|
||||
Matcher m = p.matcher(source);
|
||||
|
||||
if (m.matches()) {
|
||||
// Protected page - check access token and redirect to login page
|
||||
if (!request.getSession().getAttribute("secAttr").equals("secValue")) {
|
||||
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/login");
|
||||
dispatcher.forward(request, response);
|
||||
} else {
|
||||
// Not protected page - render content
|
||||
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(source);
|
||||
dispatcher.include(request, response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,52 @@
|
||||
edges
|
||||
| DotRegexServlet.java:11:30:11:46 | PROTECTED_PATTERN : String | DotRegexServlet.java:20:31:20:47 | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:11:30:11:46 | PROTECTED_PATTERN : String | DotRegexServlet.java:58:36:58:52 | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:11:30:11:46 | PROTECTED_PATTERN : String | DotRegexServlet.java:76:37:76:53 | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:11:50:11:64 | "/protected/.*" : String | DotRegexServlet.java:11:30:11:46 | PROTECTED_PATTERN : String |
|
||||
| DotRegexServlet.java:18:19:18:39 | getPathInfo(...) : String | DotRegexServlet.java:21:25:21:30 | source |
|
||||
| DotRegexServlet.java:37:19:37:39 | getPathInfo(...) : String | DotRegexServlet.java:40:25:40:30 | source |
|
||||
| DotRegexServlet.java:56:19:56:41 | getRequestURI(...) : String | DotRegexServlet.java:58:21:58:26 | source |
|
||||
| DotRegexServlet.java:74:19:74:39 | getPathInfo(...) : String | DotRegexServlet.java:76:56:76:61 | source |
|
||||
| DotRegexServlet.java:92:19:92:39 | getPathInfo(...) : String | DotRegexServlet.java:95:25:95:30 | source |
|
||||
| DotRegexFilter.java:16:30:16:46 | PROTECTED_PATTERN : String | DotRegexFilter.java:31:31:31:47 | PROTECTED_PATTERN |
|
||||
| DotRegexFilter.java:16:50:16:64 | "/protected/.*" : String | DotRegexFilter.java:16:30:16:46 | PROTECTED_PATTERN : String |
|
||||
| DotRegexFilter.java:29:19:29:43 | getPathInfo(...) : String | DotRegexFilter.java:32:25:32:30 | source |
|
||||
| DotRegexFilter.java:50:19:50:43 | getPathInfo(...) : String | DotRegexFilter.java:53:25:53:30 | source |
|
||||
| DotRegexServlet.java:12:30:12:46 | PROTECTED_PATTERN : String | DotRegexServlet.java:21:31:21:47 | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:12:30:12:46 | PROTECTED_PATTERN : String | DotRegexServlet.java:59:36:59:52 | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:12:30:12:46 | PROTECTED_PATTERN : String | DotRegexServlet.java:77:37:77:53 | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:12:30:12:46 | PROTECTED_PATTERN : String | DotRegexServlet.java:114:31:114:47 | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:12:50:12:64 | "/protected/.*" : String | DotRegexServlet.java:12:30:12:46 | PROTECTED_PATTERN : String |
|
||||
| DotRegexServlet.java:19:19:19:39 | getPathInfo(...) : String | DotRegexServlet.java:22:25:22:30 | source |
|
||||
| DotRegexServlet.java:38:19:38:39 | getPathInfo(...) : String | DotRegexServlet.java:41:25:41:30 | source |
|
||||
| DotRegexServlet.java:57:19:57:41 | getRequestURI(...) : String | DotRegexServlet.java:59:21:59:26 | source |
|
||||
| DotRegexServlet.java:75:19:75:39 | getPathInfo(...) : String | DotRegexServlet.java:77:56:77:61 | source |
|
||||
| DotRegexServlet.java:93:19:93:39 | getPathInfo(...) : String | DotRegexServlet.java:96:25:96:30 | source |
|
||||
| DotRegexServlet.java:112:19:112:39 | getPathInfo(...) : String | DotRegexServlet.java:115:25:115:30 | source |
|
||||
| DotRegexServlet.java:133:19:133:39 | getPathInfo(...) : String | DotRegexServlet.java:136:25:136:30 | source |
|
||||
nodes
|
||||
| DotRegexServlet.java:11:30:11:46 | PROTECTED_PATTERN : String | semmle.label | PROTECTED_PATTERN : String |
|
||||
| DotRegexServlet.java:11:50:11:64 | "/protected/.*" : String | semmle.label | "/protected/.*" : String |
|
||||
| DotRegexServlet.java:18:19:18:39 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| DotRegexServlet.java:20:31:20:47 | PROTECTED_PATTERN | semmle.label | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:21:25:21:30 | source | semmle.label | source |
|
||||
| DotRegexServlet.java:37:19:37:39 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| DotRegexServlet.java:40:25:40:30 | source | semmle.label | source |
|
||||
| DotRegexServlet.java:56:19:56:41 | getRequestURI(...) : String | semmle.label | getRequestURI(...) : String |
|
||||
| DotRegexServlet.java:58:21:58:26 | source | semmle.label | source |
|
||||
| DotRegexServlet.java:58:36:58:52 | PROTECTED_PATTERN | semmle.label | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:74:19:74:39 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| DotRegexServlet.java:76:37:76:53 | PROTECTED_PATTERN | semmle.label | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:76:56:76:61 | source | semmle.label | source |
|
||||
| DotRegexServlet.java:92:19:92:39 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| DotRegexServlet.java:95:25:95:30 | source | semmle.label | source |
|
||||
| DotRegexFilter.java:16:30:16:46 | PROTECTED_PATTERN : String | semmle.label | PROTECTED_PATTERN : String |
|
||||
| DotRegexFilter.java:16:50:16:64 | "/protected/.*" : String | semmle.label | "/protected/.*" : String |
|
||||
| DotRegexFilter.java:29:19:29:43 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| DotRegexFilter.java:31:31:31:47 | PROTECTED_PATTERN | semmle.label | PROTECTED_PATTERN |
|
||||
| DotRegexFilter.java:32:25:32:30 | source | semmle.label | source |
|
||||
| DotRegexFilter.java:50:19:50:43 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| DotRegexFilter.java:53:25:53:30 | source | semmle.label | source |
|
||||
| DotRegexServlet.java:12:30:12:46 | PROTECTED_PATTERN : String | semmle.label | PROTECTED_PATTERN : String |
|
||||
| DotRegexServlet.java:12:50:12:64 | "/protected/.*" : String | semmle.label | "/protected/.*" : String |
|
||||
| DotRegexServlet.java:19:19:19:39 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| DotRegexServlet.java:21:31:21:47 | PROTECTED_PATTERN | semmle.label | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:22:25:22:30 | source | semmle.label | source |
|
||||
| DotRegexServlet.java:38:19:38:39 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| DotRegexServlet.java:41:25:41:30 | source | semmle.label | source |
|
||||
| DotRegexServlet.java:57:19:57:41 | getRequestURI(...) : String | semmle.label | getRequestURI(...) : String |
|
||||
| DotRegexServlet.java:59:21:59:26 | source | semmle.label | source |
|
||||
| DotRegexServlet.java:59:36:59:52 | PROTECTED_PATTERN | semmle.label | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:75:19:75:39 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| DotRegexServlet.java:77:37:77:53 | PROTECTED_PATTERN | semmle.label | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:77:56:77:61 | source | semmle.label | source |
|
||||
| DotRegexServlet.java:93:19:93:39 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| DotRegexServlet.java:96:25:96:30 | source | semmle.label | source |
|
||||
| DotRegexServlet.java:112:19:112:39 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| DotRegexServlet.java:114:31:114:47 | PROTECTED_PATTERN | semmle.label | PROTECTED_PATTERN |
|
||||
| DotRegexServlet.java:115:25:115:30 | source | semmle.label | source |
|
||||
| DotRegexServlet.java:133:19:133:39 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| DotRegexServlet.java:136:25:136:30 | source | semmle.label | source |
|
||||
subpaths
|
||||
#select
|
||||
| DotRegexServlet.java:21:25:21:30 | source | DotRegexServlet.java:18:19:18:39 | getPathInfo(...) : String | DotRegexServlet.java:21:25:21:30 | source | Potentially authentication bypass due to $@. | DotRegexServlet.java:18:19:18:39 | getPathInfo(...) | user-provided value |
|
||||
| DotRegexServlet.java:58:21:58:26 | source | DotRegexServlet.java:56:19:56:41 | getRequestURI(...) : String | DotRegexServlet.java:58:21:58:26 | source | Potentially authentication bypass due to $@. | DotRegexServlet.java:56:19:56:41 | getRequestURI(...) | user-provided value |
|
||||
| DotRegexServlet.java:76:56:76:61 | source | DotRegexServlet.java:74:19:74:39 | getPathInfo(...) : String | DotRegexServlet.java:76:56:76:61 | source | Potentially authentication bypass due to $@. | DotRegexServlet.java:74:19:74:39 | getPathInfo(...) | user-provided value |
|
||||
| DotRegexFilter.java:32:25:32:30 | source | DotRegexFilter.java:29:19:29:43 | getPathInfo(...) : String | DotRegexFilter.java:32:25:32:30 | source | Potentially authentication bypass due to $@. | DotRegexFilter.java:29:19:29:43 | getPathInfo(...) | user-provided value |
|
||||
| DotRegexServlet.java:22:25:22:30 | source | DotRegexServlet.java:19:19:19:39 | getPathInfo(...) : String | DotRegexServlet.java:22:25:22:30 | source | Potentially authentication bypass due to $@. | DotRegexServlet.java:19:19:19:39 | getPathInfo(...) | user-provided value |
|
||||
| DotRegexServlet.java:59:21:59:26 | source | DotRegexServlet.java:57:19:57:41 | getRequestURI(...) : String | DotRegexServlet.java:59:21:59:26 | source | Potentially authentication bypass due to $@. | DotRegexServlet.java:57:19:57:41 | getRequestURI(...) | user-provided value |
|
||||
| DotRegexServlet.java:77:56:77:61 | source | DotRegexServlet.java:75:19:75:39 | getPathInfo(...) : String | DotRegexServlet.java:77:56:77:61 | source | Potentially authentication bypass due to $@. | DotRegexServlet.java:75:19:75:39 | getPathInfo(...) | user-provided value |
|
||||
| DotRegexServlet.java:115:25:115:30 | source | DotRegexServlet.java:112:19:112:39 | getPathInfo(...) : String | DotRegexServlet.java:115:25:115:30 | source | Potentially authentication bypass due to $@. | DotRegexServlet.java:112:19:112:39 | getPathInfo(...) | user-provided value |
|
||||
|
||||
Reference in New Issue
Block a user