SV.SSRF.URI

Invalidated user input used as a part of URI object.

The SV.SSRF.URI checker flags cases where the Java web server application receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.

Vulnerability and risk

Server-Side Request Forgery (SSRF) is an attack vector that abuses an application to interact with the internal or external network or the machine itself. One of the enablers for this vector is the mishandling of different types of URLs, for example:

  • image files on a external server, for example, a user enters a URL to an image of their avatar for an application to download and use.
  • custom webhooks, where users specify webhook handlers or callback URLs.
  • internal requests to interact with another service to serve a specific function. Frequently, user data is sent for processing, and, if poorly handled, can result in injection attacks.

Note that SSRF is not limited to the HTTP protocol. Generally, the first request is HTTP, but in cases where the application itself performs the second request, it can use different protocols, for example, FTP, SMB, SMTP) or schemes such as file://, phar://, gopher://, data://, dict://,and so on.

If an application is vulnerable to XML eXternal Entity (XXE) injection, then it can be exploited to perform a SSRF attack

Mitigation and prevention

Ensure that the IP address provided belongs to one of the IP addresses of the identified and trusted applications.

Vulnerable code example

1 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException,URISyntaxException, InterruptedException {
2   HttpClient client = HttpClient.newHttpClient();
3   String url = req.getParameter("uri");
4   URI uri = new URI(url);
5   // BAD: a request parameter is incorporated without validation into a Http request
6   HttpRequest r = HttpRequest.newBuilder(uri).build();
7   client.send(r, null);
8   }

In this example, the String URL parameter that is extracted from the HttpServletRequest by using the req.getParameter("uri") is being used for the HttpRequest connection without any validation. Klocwork reports a defect on line 3, indicating, "Invalidated user input used as a part of URI object."

Fixed code example

1   public final String VALID_URI = "SOME_VALID_URL";
2
3
4   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, URISyntaxException, InterruptedException {
5      HttpClient client = HttpClient.newHttpClient();
6
7      // GOOD: the request parameter is validated against a known fixed string or valid source of IP address
8      String url = req.getParameter("uri");
9      if (VALID_URI.equals(url)) {
10       URI uri = new URI(url);
11       HttpRequest r = HttpRequest.newBuilder(uri).build();
12       client.send(r, null);
13     }
14  }

In this fixed example, Klocwork no longer raises a defect, because the URL parameter that is extracted from HttpServletRequest by using req.getParameter("uri") is validated against a trusted URL before being used for the HttpRequest connection.

External guidance

Extension

This checker can be tuned to check whether a user is authorized to access protected APIs that are used in the project. You can do this by using the @CheckerParam option in a .jkb file. See Tuning Java analysis for more information.