diff --git a/java/ql/src/Security/CWE/CWE-552/UnsafeLoadSpringResource.java b/java/ql/src/Security/CWE/CWE-552/UnsafeLoadSpringResource.java deleted file mode 100644 index ce462fe490efa..0000000000000 --- a/java/ql/src/Security/CWE/CWE-552/UnsafeLoadSpringResource.java +++ /dev/null @@ -1,21 +0,0 @@ -//BAD: no path validation in Spring resource loading -@GetMapping("/file") -public String getFileContent(@RequestParam(name="fileName") String fileName) { - ClassPathResource clr = new ClassPathResource(fileName); - - File file = ResourceUtils.getFile(fileName); - - Resource resource = resourceLoader.getResource(fileName); -} - -//GOOD: check for a trusted prefix, ensuring path traversal is not used to erase that prefix in Spring resource loading: -@GetMapping("/file") -public String getFileContent(@RequestParam(name="fileName") String fileName) { - if (!fileName.contains("..") && fileName.hasPrefix("/public-content")) { - ClassPathResource clr = new ClassPathResource(fileName); - - File file = ResourceUtils.getFile(fileName); - - Resource resource = resourceLoader.getResource(fileName); - } -} diff --git a/java/ql/src/Security/CWE/CWE-552/UnsafeResourceGet.java b/java/ql/src/Security/CWE/CWE-552/UnsafeResourceGet.java deleted file mode 100644 index 8b3583bf59e2c..0000000000000 --- a/java/ql/src/Security/CWE/CWE-552/UnsafeResourceGet.java +++ /dev/null @@ -1,18 +0,0 @@ -// BAD: no URI validation -URL url = request.getServletContext().getResource(requestUrl); -url = getClass().getResource(requestUrl); -InputStream in = url.openStream(); - -InputStream in = request.getServletContext().getResourceAsStream(requestPath); -in = getClass().getClassLoader().getResourceAsStream(requestPath); - -// GOOD: check for a trusted prefix, ensuring path traversal is not used to erase that prefix: -// (alternatively use `Path.normalize` instead of checking for `..`) -if (!requestPath.contains("..") && requestPath.startsWith("/trusted")) { - InputStream in = request.getServletContext().getResourceAsStream(requestPath); -} - -Path path = Paths.get(requestUrl).normalize().toRealPath(); -if (path.startsWith("/trusted")) { - URL url = request.getServletContext().getResource(path.toString()); -} diff --git a/java/ql/src/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java b/java/ql/src/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java deleted file mode 100644 index a2bbf3dfcd856..0000000000000 --- a/java/ql/src/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java +++ /dev/null @@ -1,11 +0,0 @@ -// BAD: no URI validation -String returnURL = request.getParameter("returnURL"); -RequestDispatcher rd = sc.getRequestDispatcher(returnURL); -rd.forward(request, response); - -// GOOD: check for a trusted prefix, ensuring path traversal is not used to erase that prefix: -// (alternatively use `Path.normalize` instead of checking for `..`) -if (!returnURL.contains("..") && returnURL.hasPrefix("/pages")) { ... } -// Also GOOD: check for a forbidden prefix, ensuring URL-encoding is not used to evade the check: -// (alternatively use `URLDecoder.decode` before `hasPrefix`) -if (returnURL.hasPrefix("/internal") && !returnURL.contains("%")) { ... } diff --git a/java/ql/src/Security/CWE/CWE-552/UrlForward.java b/java/ql/src/Security/CWE/CWE-552/UrlForward.java index 53b959bb88960..db701fbcd9a89 100644 --- a/java/ql/src/Security/CWE/CWE-552/UrlForward.java +++ b/java/ql/src/Security/CWE/CWE-552/UrlForward.java @@ -1,38 +1,17 @@ -import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.servlet.ModelAndView; +public class UrlForward extends HttpServlet { + private static final String VALID_FORWARD = "https://cwe.mitre.org/data/definitions/552.html"; -@Controller -public class UrlForward { + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + ServletConfig cfg = getServletConfig(); + ServletContext sc = cfg.getServletContext(); - @GetMapping("/bad1") - public ModelAndView bad1(String url) { - return new ModelAndView(url); - } - - @GetMapping("/bad2") - public void bad2(String url, HttpServletRequest request, HttpServletResponse response) { - try { - request.getRequestDispatcher("/WEB-INF/jsp/" + url + ".jsp").include(request, response); - } catch (ServletException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } + // BAD: a request parameter is incorporated without validation into a URL forward + sc.getRequestDispatcher(request.getParameter("target")).forward(request, response); - @GetMapping("/good1") - public void good1(String url, HttpServletRequest request, HttpServletResponse response) { - try { - request.getRequestDispatcher("/index.jsp?token=" + url).forward(request, response); - } catch (ServletException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); + // GOOD: the request parameter is validated against a known fixed string + if (VALID_FORWARD.equals(request.getParameter("target"))) { + sc.getRequestDispatcher(VALID_FORWARD).forward(request, response); } } } diff --git a/java/ql/src/Security/CWE/CWE-552/UrlForward.qhelp b/java/ql/src/Security/CWE/CWE-552/UrlForward.qhelp index fa9ffd45c1038..2b06a851a2b61 100644 --- a/java/ql/src/Security/CWE/CWE-552/UrlForward.qhelp +++ b/java/ql/src/Security/CWE/CWE-552/UrlForward.qhelp @@ -5,66 +5,32 @@ -

Constructing a server-side redirect path with user input could allow an attacker to download application binaries -(including application classes or jar files) or view arbitrary files within protected directories.

+

Directly incorporating user input into a URL forward request without validating the input +can cause file information disclosure by allowing an attacker to access unauthorized URLs.

-

Unsanitized user provided data must not be used to construct the path for URL forwarding. In order to prevent -untrusted URL forwarding, it is recommended to avoid concatenating user input directly into the forwarding URL. -Instead, user input should be checked against allowed (e.g., must come within user_content/) or disallowed -(e.g. must not come within /internal) paths, ensuring that neither path traversal using ../ -or URL encoding are used to evade these checks. -

+

To guard against untrusted URL forwarding, it is advisable to avoid putting user input +directly into a forwarded URL. Instead, maintain a list of authorized +URLs on the server; then choose from that list based on the user input provided.

-

The following examples show the bad case and the good case respectively. -The bad methods show an HTTP request parameter being used directly in a URL forward -without validating the input, which may cause file leakage. In the good1 method, -ordinary forwarding requests are shown, which will not cause file leakage. +

The following example shows an HTTP request parameter being used directly in a URL forward +without validating the input, which may cause file information disclosure. +It also shows how to remedy the problem by validating the user input against a known fixed string.

-

The following examples show an HTTP request parameter or request path being used directly in a -request dispatcher of Java EE without validating the input, which allows sensitive file exposure -attacks. It also shows how to remedy the problem by validating the user input. -

- - - -

The following examples show an HTTP request parameter or request path being used directly to -retrieve a resource of a Java EE application without validating the input, which allows sensitive -file exposure attacks. It also shows how to remedy the problem by validating the user input. -

- - - -

The following examples show an HTTP request parameter being used directly to retrieve a resource - of a Java Spring application without validating the input, which allows sensitive file exposure - attacks. It also shows how to remedy the problem by validating the user input. -

- -
-
  • File Disclosure: - Unsafe Url Forward. -
  • -
  • Jakarta Javadoc: - Security vulnerability with unsafe usage of RequestDispatcher. -
  • -
  • Micro Focus: - File Disclosure: J2EE -
  • -
  • CVE-2015-5174: - Apache Tomcat 6.0/7.0/8.0/9.0 Servletcontext getResource/getResourceAsStream/getResourcePaths Path Traversal -
  • -
  • CVE-2019-3799: - CVE-2019-3799 - Spring-Cloud-Config-Server Directory Traversal < 2.1.2, 2.0.4, 1.4.6 + +
  • OWASP: + Unvalidated Redirects and Forwards Cheat Sheet.
  • +
    diff --git a/java/ql/src/Security/CWE/CWE-552/UrlForward.ql b/java/ql/src/Security/CWE/CWE-552/UrlForward.ql index 66d3d0dd1ca32..95c540049a21c 100644 --- a/java/ql/src/Security/CWE/CWE-552/UrlForward.ql +++ b/java/ql/src/Security/CWE/CWE-552/UrlForward.ql @@ -1,16 +1,14 @@ /** * @name URL forward from a remote source * @description URL forward based on unvalidated user-input - * may cause file information disclosure or - * redirection to malicious web sites. + * may cause file information disclosure. * @kind path-problem * @problem.severity error - * @security-severity 6.1 + * @security-severity 7.5 * @precision high * @id java/unvalidated-url-forward * @tags security * external/cwe/cwe-552 - * external/cwe/cwe-601 */ import java