Refactor UnvalidatedCors

This commit is contained in:
Ed Minnix
2023-04-12 11:26:13 -04:00
parent d254d91f57
commit 4c80ff03de

View File

@@ -14,8 +14,7 @@ import java
import semmle.code.java.dataflow.FlowSources import semmle.code.java.dataflow.FlowSources
import semmle.code.java.frameworks.Servlets import semmle.code.java.frameworks.Servlets
import semmle.code.java.dataflow.TaintTracking import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.TaintTracking2 import CorsOriginFlow::PathGraph
import DataFlow::PathGraph
/** /**
* Holds if `header` sets `Access-Control-Allow-Credentials` to `true`. This ensures fair chances of exploitability. * Holds if `header` sets `Access-Control-Allow-Credentials` to `true`. This ensures fair chances of exploitability.
@@ -48,24 +47,25 @@ private Expr getAccessControlAllowOriginHeaderName() {
} }
/** /**
* This taintflow2 configuration checks if there is a flow from source node towards CorsProbableCheckAccess methods. * A taint-tracking configuration for flow from a source node to CorsProbableCheckAccess methods.
*/ */
class CorsSourceReachesCheckConfig extends TaintTracking2::Configuration { module CorsSourceReachesCheckConfig implements DataFlow::ConfigSig {
CorsSourceReachesCheckConfig() { this = "CorsOriginConfig" } predicate isSource(DataFlow::Node source) { CorsOriginFlow::flow(source, _) }
override predicate isSource(DataFlow::Node source) { any(CorsOriginConfig c).hasFlow(source, _) } predicate isSink(DataFlow::Node sink) {
override predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(CorsProbableCheckAccess check).getAnArgument() sink.asExpr() = any(CorsProbableCheckAccess check).getAnArgument()
} }
} }
private class CorsOriginConfig extends TaintTracking::Configuration { /**
CorsOriginConfig() { this = "CorsOriginConfig" } * Taint-tracking flow from a source node to CorsProbableCheckAccess methods.
*/
module CorsSourceReachesCheckFlow = TaintTracking::Global<CorsSourceReachesCheckConfig>;
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } private module CorsOriginConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { predicate isSink(DataFlow::Node sink) {
exists(MethodAccess corsHeader, MethodAccess allowCredentialsHeader | exists(MethodAccess corsHeader, MethodAccess allowCredentialsHeader |
( (
corsHeader.getMethod() instanceof ResponseSetHeaderMethod or corsHeader.getMethod() instanceof ResponseSetHeaderMethod or
@@ -79,9 +79,11 @@ private class CorsOriginConfig extends TaintTracking::Configuration {
} }
} }
from private module CorsOriginFlow = TaintTracking::Global<CorsOriginConfig>;
DataFlow::PathNode source, DataFlow::PathNode sink, CorsOriginConfig conf,
CorsSourceReachesCheckConfig sanconf from CorsOriginFlow::PathNode source, CorsOriginFlow::PathNode sink
where conf.hasFlowPath(source, sink) and not sanconf.hasFlow(source.getNode(), _) where
CorsOriginFlow::flowPath(source, sink) and
not CorsSourceReachesCheckFlow::flow(source.getNode(), _)
select sink.getNode(), source, sink, "CORS header is being set using user controlled value $@.", select sink.getNode(), source, sink, "CORS header is being set using user controlled value $@.",
source.getNode(), "user-provided value" source.getNode(), "user-provided value"