-
Notifications
You must be signed in to change notification settings - Fork 2k
Java: Update CWE-918 model coverage for Apache HttpClient execute sinks
#21804
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
base: main
Are you sure you want to change the base?
Changes from all commits
26dca55
f5b17b0
043ec85
dd35bc0
dc86476
d7659a0
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 |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| --- | ||
| category: minorAnalysis | ||
| --- | ||
| * Improved modeling of Apache HttpClient `execute` method sinks for `java/ssrf` and `java/non-https-url`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,11 @@ extensions: | |
| pack: codeql/java-all | ||
| extensible: sinkModel | ||
| data: | ||
| - ["org.apache.http.client", "HttpClient", True, "execute", "(HttpHost,HttpRequest)", "", "Argument[0]", "request-forgery", "ai-manual"] | ||
|
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. The models look good, but I'm not sure if maybe Argument[1] is also a sink here. The request here will have the headers of the outgoing request so if they are user controlled, they could for example cause a malicious redirect or something like that depending on the server that reads it. I will approve it, but do check this out too |
||
| - ["org.apache.http.client", "HttpClient", True, "execute", "(HttpHost,HttpRequest,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"] | ||
| - ["org.apache.http.client", "HttpClient", True, "execute", "(HttpHost,HttpRequest,ResponseHandler)", "", "Argument[0]", "request-forgery", "ai-manual"] | ||
| - ["org.apache.http.client", "HttpClient", True, "execute", "(HttpHost,HttpRequest,ResponseHandler,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"] | ||
| - ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest)", "", "Argument[0]", "request-forgery", "ai-manual"] | ||
| - ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"] | ||
| - ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest,ResponseHandler)", "", "Argument[0]", "request-forgery", "ai-manual"] | ||
| - ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest,ResponseHandler,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"] | ||
| - ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest)", "", "Argument[0]", "request-forgery", "ai-manual"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,195 @@ | ||
| import java.io.IOException; | ||
| import java.net.URI; | ||
|
|
||
| import org.apache.http.Header; | ||
| import org.apache.http.HeaderIterator; | ||
| import org.apache.http.HttpHost; | ||
| import org.apache.http.HttpRequest; | ||
| import org.apache.http.HttpResponse; | ||
| import org.apache.http.ProtocolVersion; | ||
| import org.apache.http.RequestLine; | ||
| import org.apache.http.client.HttpClient; | ||
| import org.apache.http.client.ResponseHandler; | ||
| import org.apache.http.client.methods.HttpUriRequest; | ||
| import org.apache.http.message.BasicHttpRequest; | ||
| import org.apache.http.params.HttpParams; | ||
| import org.apache.http.protocol.HttpContext; | ||
| import javax.servlet.ServletException; | ||
| import javax.servlet.http.HttpServlet; | ||
| import javax.servlet.http.HttpServletRequest; | ||
| import javax.servlet.http.HttpServletResponse; | ||
|
|
||
| public class ApacheHttpClientExecuteSSRF extends HttpServlet { | ||
|
|
||
| protected void doGet(HttpServletRequest request, HttpServletResponse response) | ||
| throws ServletException, IOException { | ||
| try { | ||
|
|
||
| String sink = request.getParameter("host"); // $ Source | ||
|
|
||
| HttpHost host = new HttpHost(sink); | ||
| HttpRequest req = new BasicHttpRequest("GET", "/"); | ||
| HttpUriRequest uriReq = new HttpUriRequest() { | ||
| @Override | ||
| public String getMethod() { | ||
| return "GET"; | ||
| } | ||
|
|
||
| @Override | ||
| public URI getURI() { | ||
| return URI.create("https://" + sink); | ||
| } | ||
|
|
||
| @Override | ||
| public void abort() throws UnsupportedOperationException { | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isAborted() { | ||
| return false; | ||
| } | ||
|
|
||
| @Override | ||
| public RequestLine getRequestLine() { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public ProtocolVersion getProtocolVersion() { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean containsHeader(String name) { | ||
| return false; | ||
| } | ||
|
|
||
| @Override | ||
| public Header[] getHeaders(String name) { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public Header getFirstHeader(String name) { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public Header getLastHeader(String name) { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public Header[] getAllHeaders() { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public void addHeader(Header header) { | ||
| } | ||
|
|
||
| @Override | ||
| public void addHeader(String name, String value) { | ||
| } | ||
|
|
||
| @Override | ||
| public void setHeader(Header header) { | ||
| } | ||
|
|
||
| @Override | ||
| public void setHeader(String name, String value) { | ||
| } | ||
|
|
||
| @Override | ||
| public void setHeaders(Header[] headers) { | ||
| } | ||
|
|
||
| @Override | ||
| public void removeHeader(Header header) { | ||
| } | ||
|
|
||
| @Override | ||
| public void removeHeaders(String name) { | ||
| } | ||
|
|
||
| @Override | ||
| public HeaderIterator headerIterator() { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public HeaderIterator headerIterator(String name) { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public HttpParams getParams() { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public void setParams(HttpParams params) { | ||
| } | ||
| }; | ||
| HttpContext context = null; | ||
| HttpClient client = new HttpClient() { | ||
| @Override | ||
| public HttpResponse execute(HttpHost target, HttpRequest request) throws IOException { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws IOException { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler) | ||
| throws IOException { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler, | ||
| HttpContext context) throws IOException { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public HttpResponse execute(HttpUriRequest request) throws IOException { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public HttpResponse execute(HttpUriRequest request, HttpContext context) throws IOException { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler) | ||
| throws IOException { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler, | ||
| HttpContext context) throws IOException { | ||
| return null; | ||
| } | ||
| }; | ||
| ResponseHandler<Object> handler = null; | ||
|
Comment on lines
+30
to
+180
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. I agree that this is confusing. Also, the source is named sink, which is confusing as well. |
||
|
|
||
| client.execute(host, req); // $ Alert | ||
| client.execute(host, req, context); // $ Alert | ||
| client.execute(host, req, handler); // $ Alert | ||
| client.execute(host, req, handler, context); // $ Alert | ||
| client.execute(uriReq); // $ Alert | ||
| client.execute(uriReq, context); // $ Alert | ||
| client.execute(uriReq, handler); // $ Alert | ||
| client.execute(uriReq, handler, context); // $ Alert | ||
|
|
||
| } catch (Exception e) { | ||
| // TODO: handle exception | ||
| } | ||
| } | ||
| } | ||
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.
Is this right? Based on the type names and the models below, which target the
HttpUriRequestargument, I'd expect the sink to be theHttpRequestargument (possibly in addition toHttpHost).