mirror of
https://github.com/github/codeql.git
synced 2025-12-20 18:56:32 +01:00
Refactor JsonpInjection
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
import java
|
import java
|
||||||
import semmle.code.java.dataflow.DataFlow
|
import semmle.code.java.dataflow.DataFlow
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import DataFlow::PathGraph
|
|
||||||
|
|
||||||
/** Json string type data. */
|
/** Json string type data. */
|
||||||
abstract class JsonStringSource extends DataFlow::Node { }
|
abstract class JsonStringSource extends DataFlow::Node { }
|
||||||
|
|||||||
@@ -12,35 +12,37 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java
|
import java
|
||||||
import JsonpInjectionLib
|
import semmle.code.java.dataflow.TaintTracking
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import semmle.code.java.deadcode.WebEntryPoints
|
import semmle.code.java.deadcode.WebEntryPoints
|
||||||
import DataFlow::PathGraph
|
import semmle.code.java.security.XSS
|
||||||
|
import JsonpInjectionLib
|
||||||
|
import RequestResponseFlow::PathGraph
|
||||||
|
|
||||||
/** Taint-tracking configuration tracing flow from get method request sources to output jsonp data. */
|
/** Taint-tracking configuration tracing flow from get method request sources to output jsonp data. */
|
||||||
class RequestResponseFlowConfig extends TaintTracking::Configuration {
|
module RequestResponseFlowConfig implements DataFlow::ConfigSig {
|
||||||
RequestResponseFlowConfig() { this = "RequestResponseFlowConfig" }
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
|
||||||
source instanceof RemoteFlowSource and
|
source instanceof RemoteFlowSource and
|
||||||
any(RequestGetMethod m).polyCalls*(source.getEnclosingCallable())
|
any(RequestGetMethod m).polyCalls*(source.getEnclosingCallable())
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
predicate isSink(DataFlow::Node sink) {
|
||||||
sink instanceof XssSink and
|
sink instanceof XssSink and
|
||||||
any(RequestGetMethod m).polyCalls*(sink.getEnclosingCallable())
|
any(RequestGetMethod m).polyCalls*(sink.getEnclosingCallable())
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||||
exists(MethodAccess ma |
|
exists(MethodAccess ma |
|
||||||
isRequestGetParamMethod(ma) and pred.asExpr() = ma.getQualifier() and succ.asExpr() = ma
|
isRequestGetParamMethod(ma) and pred.asExpr() = ma.getQualifier() and succ.asExpr() = ma
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from DataFlow::PathNode source, DataFlow::PathNode sink, RequestResponseFlowConfig conf
|
module RequestResponseFlow = TaintTracking::Global<RequestResponseFlowConfig>;
|
||||||
|
|
||||||
|
from RequestResponseFlow::PathNode source, RequestResponseFlow::PathNode sink
|
||||||
where
|
where
|
||||||
conf.hasFlowPath(source, sink) and
|
RequestResponseFlow::flowPath(source, sink) and
|
||||||
exists(JsonpInjectionFlowConfig jhfc | jhfc.hasFlowTo(sink.getNode()))
|
JsonpInjectionFlow::flowTo(sink.getNode())
|
||||||
select sink.getNode(), source, sink, "Jsonp response might include code from $@.", source.getNode(),
|
select sink.getNode(), source, sink, "Jsonp response might include code from $@.", source.getNode(),
|
||||||
"this user input"
|
"this user input"
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import java
|
import java
|
||||||
import DataFlow
|
private import JsonStringLib
|
||||||
import JsonStringLib
|
private import semmle.code.java.security.XSS
|
||||||
import semmle.code.java.security.XSS
|
private import semmle.code.java.dataflow.TaintTracking
|
||||||
import semmle.code.java.dataflow.DataFlow
|
private import semmle.code.java.dataflow.FlowSources
|
||||||
import semmle.code.java.dataflow.DataFlow3
|
private import semmle.code.java.frameworks.spring.SpringController
|
||||||
import semmle.code.java.dataflow.FlowSources
|
|
||||||
import semmle.code.java.frameworks.spring.SpringController
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A method that is called to handle an HTTP GET request.
|
* A method that is called to handle an HTTP GET request.
|
||||||
@@ -81,38 +79,38 @@ class JsonpBuilderExpr extends AddExpr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A data flow configuration tracing flow from remote sources to jsonp function name. */
|
/** A data flow configuration tracing flow from remote sources to jsonp function name. */
|
||||||
class RemoteFlowConfig extends DataFlow2::Configuration {
|
module RemoteFlowConfig implements DataFlow::ConfigSig {
|
||||||
RemoteFlowConfig() { this = "RemoteFlowConfig" }
|
predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(JsonpBuilderExpr jhe | jhe.getFunctionName() = sink.asExpr())
|
exists(JsonpBuilderExpr jhe | jhe.getFunctionName() = sink.asExpr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module RemoteFlow = DataFlow::Global<RemoteFlowConfig>;
|
||||||
|
|
||||||
/** A data flow configuration tracing flow from json data into the argument `json` of JSONP-like string `someFunctionName + "(" + json + ")"`. */
|
/** A data flow configuration tracing flow from json data into the argument `json` of JSONP-like string `someFunctionName + "(" + json + ")"`. */
|
||||||
class JsonDataFlowConfig extends DataFlow2::Configuration {
|
module JsonDataFlowConfig implements DataFlow::ConfigSig {
|
||||||
JsonDataFlowConfig() { this = "JsonDataFlowConfig" }
|
predicate isSource(DataFlow::Node src) { src instanceof JsonStringSource }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) { src instanceof JsonStringSource }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(JsonpBuilderExpr jhe | jhe.getJsonExpr() = sink.asExpr())
|
exists(JsonpBuilderExpr jhe | jhe.getJsonExpr() = sink.asExpr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Taint-tracking configuration tracing flow from probable jsonp data with a user-controlled function name to an outgoing HTTP entity. */
|
module JsonDataFlow = DataFlow::Global<JsonDataFlowConfig>;
|
||||||
class JsonpInjectionFlowConfig extends TaintTracking::Configuration {
|
|
||||||
JsonpInjectionFlowConfig() { this = "JsonpInjectionFlowConfig" }
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) {
|
/** Taint-tracking configuration tracing flow from probable jsonp data with a user-controlled function name to an outgoing HTTP entity. */
|
||||||
exists(JsonpBuilderExpr jhe, JsonDataFlowConfig jdfc, RemoteFlowConfig rfc |
|
module JsonpInjectionFlowConfig implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node src) {
|
||||||
|
exists(JsonpBuilderExpr jhe |
|
||||||
jhe = src.asExpr() and
|
jhe = src.asExpr() and
|
||||||
jdfc.hasFlowTo(DataFlow::exprNode(jhe.getJsonExpr())) and
|
JsonDataFlow::flowTo(DataFlow::exprNode(jhe.getJsonExpr())) and
|
||||||
rfc.hasFlowTo(DataFlow::exprNode(jhe.getFunctionName()))
|
RemoteFlow::flowTo(DataFlow::exprNode(jhe.getFunctionName()))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
|
predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module JsonpInjectionFlow = TaintTracking::Global<JsonpInjectionFlowConfig>;
|
||||||
|
|||||||
Reference in New Issue
Block a user