Query to detect unsafe getResource calls in Java EE applications

This commit is contained in:
luchua-bc
2022-04-09 01:14:15 +00:00
parent 626770aaab
commit eccd97c7b7
7 changed files with 207 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
// BAD: no URI validation
URL url = servletContext.getResource(requestUrl);
InputStream in = url.openStream();
InputStream in = request.getServletContext().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();
URL url = sc.getResource(path.toString());

View File

@@ -36,6 +36,13 @@ attacks. It also shows how to remedy the problem by validating the user input.
<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" />
</example>
<references>
<li>File Disclosure:
@@ -47,5 +54,8 @@ attacks. It also shows how to remedy the problem by validating the user input.
<li>Micro Focus:
<a href="https://vulncat.fortify.com/en/detail?id=desc.dataflow.java.file_disclosure_j2ee">File Disclosure: J2EE</a>
</li>
<li>
<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>
</references>
</qhelp>

View File

@@ -1,4 +1,5 @@
import java
import experimental.semmle.code.java.frameworks.Jsf
import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.dataflow.StringPrefixes
@@ -18,6 +19,49 @@ private class RequestDispatcherSink extends UnsafeUrlForwardSink {
}
}
/** The JBoss class `FileResourceManager`. */
class FileResourceManager extends RefType {
FileResourceManager() {
this.hasQualifiedName("io.undertow.server.handlers.resource", "FileResourceManager")
}
}
/** The JBoss method `getResource` of `FileResourceManager`. */
class GetWildflyResourceMethod extends Method {
GetWildflyResourceMethod() {
this.getDeclaringType().getASupertype*() instanceof FileResourceManager and
this.hasName("getResource")
}
}
/** The JBoss class `VirtualFile`. */
class VirtualFile extends RefType {
VirtualFile() { this.hasQualifiedName("org.jboss.vfs", "VirtualFile") }
}
/** The JBoss method `getChild` of `FileResourceManager`. */
class GetVirtualFileMethod extends Method {
GetVirtualFileMethod() {
this.getDeclaringType().getASupertype*() instanceof VirtualFile and
this.hasName("getChild")
}
}
/** An argument to `getResource()` or `getResourceAsStream()`. */
private class GetResourceSink extends UnsafeUrlForwardSink {
GetResourceSink() {
exists(MethodAccess ma |
(
ma.getMethod() instanceof GetServletResourceMethod or
ma.getMethod() instanceof GetFacesResourceMethod or
ma.getMethod() instanceof GetWildflyResourceMethod or
ma.getMethod() instanceof GetVirtualFileMethod
) and
ma.getArgument(0) = this.asExpr()
)
}
}
/** An argument to `new ModelAndView` or `ModelAndView.setViewName`. */
private class SpringModelAndViewSink extends UnsafeUrlForwardSink {
SpringModelAndViewSink() {

View File

@@ -0,0 +1,24 @@
/**
* Provides classes and predicates for working with the Java Server Faces (JSF).
*/
import semmle.code.java.Type
/**
* The JSF class `FacesContext` for processing HTTP requests.
*/
class ExternalContext extends RefType {
ExternalContext() {
this.hasQualifiedName(["javax.faces.context", "jakarta.faces.context"], "ExternalContext")
}
}
/**
* The methods `getResource()` and `getResourceAsStream()` declared in JSF `ExternalContext`.
*/
class GetFacesResourceMethod extends Method {
GetFacesResourceMethod() {
this.getDeclaringType().getASupertype*() instanceof ExternalContext and
this.hasName(["getResource", "getResourceAsStream"])
}
}