mirror of
https://github.com/github/codeql.git
synced 2026-04-26 01:05:15 +02:00
Java: update qhelp
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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("%")) { ... }
|
||||
@@ -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);
|
||||
}
|
||||
// BAD: a request parameter is incorporated without validation into a URL forward
|
||||
sc.getRequestDispatcher(request.getParameter("target")).forward(request, response);
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,66 +5,32 @@
|
||||
|
||||
|
||||
<overview>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>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 <code>user_content/</code>) or disallowed
|
||||
(e.g. must not come within <code>/internal</code>) paths, ensuring that neither path traversal using <code>../</code>
|
||||
or URL encoding are used to evade these checks.
|
||||
</p>
|
||||
<p>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.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>The following examples show the bad case and the good case respectively.
|
||||
The <code>bad</code> methods show an HTTP request parameter being used directly in a URL forward
|
||||
without validating the input, which may cause file leakage. In the <code>good1</code> method,
|
||||
ordinary forwarding requests are shown, which will not cause file leakage.
|
||||
<p>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.
|
||||
</p>
|
||||
|
||||
<sample src="UrlForward.java" />
|
||||
|
||||
<p>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.
|
||||
</p>
|
||||
|
||||
<sample src="UnsafeServletRequestDispatch.java" />
|
||||
|
||||
<p>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.
|
||||
</p>
|
||||
|
||||
<sample src="UnsafeResourceGet.java" />
|
||||
|
||||
<p>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.
|
||||
</p>
|
||||
|
||||
<sample src="UnsafeLoadSpringResource.java" />
|
||||
</example>
|
||||
<references>
|
||||
<li>File Disclosure:
|
||||
<a href="https://vulncat.fortify.com/en/detail?id=desc.dataflow.java.file_disclosure_spring">Unsafe Url Forward</a>.
|
||||
</li>
|
||||
<li>Jakarta Javadoc:
|
||||
<a href="https://jakarta.ee/specifications/webprofile/9/apidocs/jakarta/servlet/servletrequest#getRequestDispatcher-java.lang.String-">Security vulnerability with unsafe usage of RequestDispatcher</a>.
|
||||
</li>
|
||||
<li>Micro Focus:
|
||||
<a href="https://vulncat.fortify.com/en/detail?id=desc.dataflow.java.file_disclosure_j2ee">File Disclosure: J2EE</a>
|
||||
</li>
|
||||
<li>CVE-2015-5174:
|
||||
<a href="https://vuldb.com/?id.81084">Apache Tomcat 6.0/7.0/8.0/9.0 Servletcontext getResource/getResourceAsStream/getResourcePaths Path Traversal</a>
|
||||
</li>
|
||||
<li>CVE-2019-3799:
|
||||
<a href="https://github.com/mpgn/CVE-2019-3799">CVE-2019-3799 - Spring-Cloud-Config-Server Directory Traversal < 2.1.2, 2.0.4, 1.4.6</a>
|
||||
|
||||
<li>OWASP:
|
||||
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html">Unvalidated Redirects and Forwards Cheat Sheet</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user