Java: move config to Query.qll file

This commit is contained in:
Jami Cogswell
2023-11-20 16:56:41 -05:00
parent 0d38a9625e
commit 2793f28428
5 changed files with 105 additions and 46 deletions

View File

@@ -0,0 +1,35 @@
/**
* Provides classes and predicates for working with the Java Server Faces (JSF).
*/
// TODO: COMBINE WITH EXISTING JSF-RELATED QLL FILES!
import java
/**
* The JSF class `ExternalContext` for processing HTTP requests.
*/
class ExternalContext extends RefType {
ExternalContext() {
this.hasQualifiedName(["javax.faces.context", "jakarta.faces.context"], "ExternalContext")
}
}
/**
* The method `getResource()` declared in JSF `ExternalContext`.
*/
class GetFacesResourceMethod extends Method {
GetFacesResourceMethod() {
this.getDeclaringType().getASupertype*() instanceof ExternalContext and
this.hasName("getResource")
}
}
/**
* The method `getResourceAsStream()` declared in JSF `ExternalContext`.
*/
class GetFacesResourceAsStreamMethod extends Method {
GetFacesResourceAsStreamMethod() {
this.getDeclaringType().getASupertype*() instanceof ExternalContext and
this.hasName("getResourceAsStream")
}
}

View File

@@ -0,0 +1,22 @@
/**
* Provides classes for working with resource loading in Spring.
*/
// TODO: COMBINE WITH EXISTING SPRING-RELATED QLL FILES!
import java
private import semmle.code.java.dataflow.FlowSources
/** A utility class for resolving resource locations to files in the file system in the Spring framework. */
class ResourceUtils extends Class {
ResourceUtils() { this.hasQualifiedName("org.springframework.util", "ResourceUtils") }
}
/**
* A method declared in `org.springframework.util.ResourceUtils` that loads Spring resources.
*/
class GetResourceUtilsMethod extends Method {
GetResourceUtilsMethod() {
this.getDeclaringType().getASupertype*() instanceof ResourceUtils and
this.hasName(["extractArchiveURL", "extractJarFileURL", "getFile", "getURL"])
}
}

View File

@@ -0,0 +1,163 @@
import java
private import semmle.code.java.Jsf
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.dataflow.StringPrefixes
private import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
private import semmle.code.java.SpringResource
/** A sink for unsafe URL forward vulnerabilities. */
abstract class UnsafeUrlForwardSink extends DataFlow::Node { }
/** A sanitizer for unsafe URL forward vulnerabilities. */
abstract class UnsafeUrlForwardSanitizer extends DataFlow::Node { }
/** An argument to `getRequestDispatcher`. */
private class RequestDispatcherSink extends UnsafeUrlForwardSink {
RequestDispatcherSink() {
exists(MethodCall ma |
ma.getMethod() instanceof GetRequestDispatcherMethod and
ma.getArgument(0) = this.asExpr()
)
}
}
/** The `getResource` method of `Class`. */
class GetClassResourceMethod extends Method {
GetClassResourceMethod() {
this.getDeclaringType() instanceof TypeClass and
this.hasName("getResource")
}
}
/** The `getResourceAsStream` method of `Class`. */
class GetClassResourceAsStreamMethod extends Method {
GetClassResourceAsStreamMethod() {
this.getDeclaringType() instanceof TypeClass and
this.hasName("getResourceAsStream")
}
}
/** The `getResource` method of `ClassLoader`. */
class GetClassLoaderResourceMethod extends Method {
GetClassLoaderResourceMethod() {
this.getDeclaringType() instanceof ClassLoaderClass and
this.hasName("getResource")
}
}
/** The `getResourceAsStream` method of `ClassLoader`. */
class GetClassLoaderResourceAsStreamMethod extends Method {
GetClassLoaderResourceAsStreamMethod() {
this.getDeclaringType() instanceof ClassLoaderClass and
this.hasName("getResourceAsStream")
}
}
/** 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 GetVirtualFileChildMethod extends Method {
GetVirtualFileChildMethod() {
this.getDeclaringType().getASupertype*() instanceof VirtualFile and
this.hasName("getChild")
}
}
/** An argument to `getResource()` or `getResourceAsStream()`. */
private class GetResourceSink extends UnsafeUrlForwardSink {
GetResourceSink() {
sinkNode(this, "request-forgery")
or
sinkNode(this, "get-resource")
or
exists(MethodCall ma |
(
ma.getMethod() instanceof GetServletResourceAsStreamMethod or
ma.getMethod() instanceof GetFacesResourceAsStreamMethod or
ma.getMethod() instanceof GetClassResourceAsStreamMethod or
ma.getMethod() instanceof GetClassLoaderResourceAsStreamMethod or
ma.getMethod() instanceof GetVirtualFileChildMethod
) and
ma.getArgument(0) = this.asExpr()
)
}
}
/** A sink for methods that load Spring resources. */
private class SpringResourceSink extends UnsafeUrlForwardSink {
SpringResourceSink() {
exists(MethodCall ma |
ma.getMethod() instanceof GetResourceUtilsMethod and
ma.getArgument(0) = this.asExpr()
)
}
}
/** An argument to `new ModelAndView` or `ModelAndView.setViewName`. */
private class SpringModelAndViewSink extends UnsafeUrlForwardSink {
SpringModelAndViewSink() {
exists(ClassInstanceExpr cie |
cie.getConstructedType() instanceof ModelAndView and
cie.getArgument(0) = this.asExpr()
)
or
exists(SpringModelAndViewSetViewNameCall smavsvnc | smavsvnc.getArgument(0) = this.asExpr())
}
}
private class PrimitiveSanitizer extends UnsafeUrlForwardSanitizer {
PrimitiveSanitizer() {
this.getType() instanceof PrimitiveType or
this.getType() instanceof BoxedType or
this.getType() instanceof NumberType
}
}
private class SanitizingPrefix extends InterestingPrefix {
SanitizingPrefix() {
not this.getStringValue().matches("/WEB-INF/%") and
not this.getStringValue() = "forward:"
}
override int getOffset() { result = 0 }
}
private class FollowsSanitizingPrefix extends UnsafeUrlForwardSanitizer {
FollowsSanitizingPrefix() { this.asExpr() = any(SanitizingPrefix fp).getAnAppendedExpression() }
}
private class ForwardPrefix extends InterestingPrefix {
ForwardPrefix() { this.getStringValue() = "forward:" }
override int getOffset() { result = 0 }
}
/**
* An expression appended (perhaps indirectly) to `"forward:"`, and which
* is reachable from a Spring entry point.
*/
private class SpringUrlForwardSink extends UnsafeUrlForwardSink {
SpringUrlForwardSink() {
any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable()) and
this.asExpr() = any(ForwardPrefix fp).getAnAppendedExpression()
}
}

View File

@@ -0,0 +1,45 @@
import java
import semmle.code.java.security.UnsafeUrlForward
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.Jsf
import semmle.code.java.security.PathSanitizer
module UnsafeUrlForwardFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof ThreatModelFlowSource and
not exists(MethodCall ma, Method m | ma.getMethod() = m |
(
m instanceof HttpServletRequestGetRequestUriMethod or
m instanceof HttpServletRequestGetRequestUrlMethod or
m instanceof HttpServletRequestGetPathMethod
) and
ma = source.asExpr()
)
}
predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeUrlForwardSink }
predicate isBarrier(DataFlow::Node node) {
node instanceof UnsafeUrlForwardSanitizer or
node instanceof PathInjectionSanitizer
}
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
predicate isAdditionalFlowStep(DataFlow::Node prev, DataFlow::Node succ) {
exists(MethodCall ma |
(
ma.getMethod() instanceof GetServletResourceMethod or
ma.getMethod() instanceof GetFacesResourceMethod or
ma.getMethod() instanceof GetClassResourceMethod or
ma.getMethod() instanceof GetClassLoaderResourceMethod or
ma.getMethod() instanceof GetWildflyResourceMethod
) and
ma.getArgument(0) = prev.asExpr() and
ma = succ.asExpr()
)
}
}
module UnsafeUrlForwardFlow = TaintTracking::Global<UnsafeUrlForwardFlowConfig>;