mirror of
https://github.com/github/codeql.git
synced 2025-12-23 04:06:37 +01:00
Merge pull request #12542 from egregius313/egregius313/refactor-more-queries-to-dataflow-module-api
Java: Refactor more queries to the new DataFlow module API (part 2)
This commit is contained in:
@@ -16,16 +16,13 @@ import semmle.code.java.Expr
|
|||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import semmle.code.java.security.ExternalProcess
|
import semmle.code.java.security.ExternalProcess
|
||||||
import semmle.code.java.security.CommandArguments
|
import semmle.code.java.security.CommandArguments
|
||||||
import DataFlow::PathGraph
|
|
||||||
|
|
||||||
class LocalUserInputToArgumentToExecFlowConfig extends TaintTracking::Configuration {
|
module LocalUserInputToArgumentToExecFlowConfig implements DataFlow::ConfigSig {
|
||||||
LocalUserInputToArgumentToExecFlowConfig() { this = "LocalUserInputToArgumentToExecFlowConfig" }
|
predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput }
|
predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof ArgumentToExec }
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof ArgumentToExec }
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
node.getType() instanceof PrimitiveType
|
node.getType() instanceof PrimitiveType
|
||||||
or
|
or
|
||||||
node.getType() instanceof BoxedType
|
node.getType() instanceof BoxedType
|
||||||
@@ -34,9 +31,16 @@ class LocalUserInputToArgumentToExecFlowConfig extends TaintTracking::Configurat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module LocalUserInputToArgumentToExecFlow =
|
||||||
|
TaintTracking::Make<LocalUserInputToArgumentToExecFlowConfig>;
|
||||||
|
|
||||||
|
import LocalUserInputToArgumentToExecFlow::PathGraph
|
||||||
|
|
||||||
from
|
from
|
||||||
DataFlow::PathNode source, DataFlow::PathNode sink, ArgumentToExec execArg,
|
LocalUserInputToArgumentToExecFlow::PathNode source,
|
||||||
LocalUserInputToArgumentToExecFlowConfig conf
|
LocalUserInputToArgumentToExecFlow::PathNode sink, ArgumentToExec execArg
|
||||||
where conf.hasFlowPath(source, sink) and sink.getNode().asExpr() = execArg
|
where
|
||||||
|
LocalUserInputToArgumentToExecFlow::hasFlowPath(source, sink) and
|
||||||
|
sink.getNode().asExpr() = execArg
|
||||||
select execArg, source, sink, "This command line depends on a $@.", source.getNode(),
|
select execArg, source, sink, "This command line depends on a $@.", source.getNode(),
|
||||||
"user-provided value"
|
"user-provided value"
|
||||||
|
|||||||
@@ -14,17 +14,18 @@
|
|||||||
import java
|
import java
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import semmle.code.java.security.XSS
|
import semmle.code.java.security.XSS
|
||||||
import DataFlow::PathGraph
|
|
||||||
|
|
||||||
class XssLocalConfig extends TaintTracking::Configuration {
|
module XssLocalConfig implements DataFlow::ConfigSig {
|
||||||
XssLocalConfig() { this = "XSSLocalConfig" }
|
predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
|
predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
from DataFlow::PathNode source, DataFlow::PathNode sink, XssLocalConfig conf
|
module XssLocalFlow = TaintTracking::Make<XssLocalConfig>;
|
||||||
where conf.hasFlowPath(source, sink)
|
|
||||||
|
import XssLocalFlow::PathGraph
|
||||||
|
|
||||||
|
from XssLocalFlow::PathNode source, XssLocalFlow::PathNode sink
|
||||||
|
where XssLocalFlow::hasFlowPath(source, sink)
|
||||||
select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to $@.",
|
select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to $@.",
|
||||||
source.getNode(), "user-provided value"
|
source.getNode(), "user-provided value"
|
||||||
|
|||||||
@@ -25,28 +25,27 @@ class UncontrolledStringBuilderSource extends DataFlow::ExprNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UncontrolledStringBuilderSourceFlowConfig extends TaintTracking::Configuration {
|
module UncontrolledStringBuilderSourceFlowConfig implements DataFlow::ConfigSig {
|
||||||
UncontrolledStringBuilderSourceFlowConfig() {
|
predicate isSource(DataFlow::Node src) { src instanceof UncontrolledStringBuilderSource }
|
||||||
this = "SqlConcatenated::UncontrolledStringBuilderSourceFlowConfig"
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) { src instanceof UncontrolledStringBuilderSource }
|
predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module UncontrolledStringBuilderSourceFlow =
|
||||||
|
TaintTracking::Make<UncontrolledStringBuilderSourceFlowConfig>;
|
||||||
|
|
||||||
from QueryInjectionSink query, Expr uncontrolled
|
from QueryInjectionSink query, Expr uncontrolled
|
||||||
where
|
where
|
||||||
(
|
(
|
||||||
builtFromUncontrolledConcat(query.asExpr(), uncontrolled)
|
builtFromUncontrolledConcat(query.asExpr(), uncontrolled)
|
||||||
or
|
or
|
||||||
exists(StringBuilderVar sbv, UncontrolledStringBuilderSourceFlowConfig conf |
|
exists(StringBuilderVar sbv |
|
||||||
uncontrolledStringBuilderQuery(sbv, uncontrolled) and
|
uncontrolledStringBuilderQuery(sbv, uncontrolled) and
|
||||||
conf.hasFlow(DataFlow::exprNode(sbv.getToStringCall()), query)
|
UncontrolledStringBuilderSourceFlow::hasFlow(DataFlow::exprNode(sbv.getToStringCall()), query)
|
||||||
)
|
)
|
||||||
) and
|
) and
|
||||||
not queryTaintedBy(query, _, _)
|
not queryTaintedBy(query, _, _)
|
||||||
|
|||||||
@@ -15,26 +15,29 @@
|
|||||||
import semmle.code.java.Expr
|
import semmle.code.java.Expr
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import semmle.code.java.security.SqlInjectionQuery
|
import semmle.code.java.security.SqlInjectionQuery
|
||||||
import DataFlow::PathGraph
|
|
||||||
|
|
||||||
class LocalUserInputToQueryInjectionFlowConfig extends TaintTracking::Configuration {
|
module LocalUserInputToQueryInjectionFlowConfig implements DataFlow::ConfigSig {
|
||||||
LocalUserInputToQueryInjectionFlowConfig() { this = "LocalUserInputToQueryInjectionFlowConfig" }
|
predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput }
|
predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||||
any(AdditionalQueryInjectionTaintStep s).step(node1, node2)
|
any(AdditionalQueryInjectionTaintStep s).step(node1, node2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module LocalUserInputToQueryInjectionFlow =
|
||||||
|
TaintTracking::Make<LocalUserInputToQueryInjectionFlowConfig>;
|
||||||
|
|
||||||
|
import LocalUserInputToQueryInjectionFlow::PathGraph
|
||||||
|
|
||||||
from
|
from
|
||||||
DataFlow::PathNode source, DataFlow::PathNode sink, LocalUserInputToQueryInjectionFlowConfig conf
|
LocalUserInputToQueryInjectionFlow::PathNode source,
|
||||||
where conf.hasFlowPath(source, sink)
|
LocalUserInputToQueryInjectionFlow::PathNode sink
|
||||||
|
where LocalUserInputToQueryInjectionFlow::hasFlowPath(source, sink)
|
||||||
select sink.getNode(), source, sink, "This query depends on a $@.", source.getNode(),
|
select sink.getNode(), source, sink, "This query depends on a $@.", source.getNode(),
|
||||||
"user-provided value"
|
"user-provided value"
|
||||||
|
|||||||
@@ -13,25 +13,28 @@
|
|||||||
import java
|
import java
|
||||||
import ArraySizing
|
import ArraySizing
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import DataFlow::PathGraph
|
|
||||||
|
|
||||||
class Conf extends TaintTracking::Configuration {
|
private module ImproperValidationOfArrayConstructionConfig implements DataFlow::ConfigSig {
|
||||||
Conf() { this = "RemoteUserInputTocanThrowOutOfBoundsDueToEmptyArrayConfig" }
|
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
any(CheckableArrayAccess caa).canThrowOutOfBoundsDueToEmptyArray(sink.asExpr(), _)
|
any(CheckableArrayAccess caa).canThrowOutOfBoundsDueToEmptyArray(sink.asExpr(), _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module ImproperValidationOfArrayConstructionFlow =
|
||||||
|
TaintTracking::Make<ImproperValidationOfArrayConstructionConfig>;
|
||||||
|
|
||||||
|
import ImproperValidationOfArrayConstructionFlow::PathGraph
|
||||||
|
|
||||||
from
|
from
|
||||||
DataFlow::PathNode source, DataFlow::PathNode sink, Expr sizeExpr,
|
ImproperValidationOfArrayConstructionFlow::PathNode source,
|
||||||
|
ImproperValidationOfArrayConstructionFlow::PathNode sink, Expr sizeExpr,
|
||||||
ArrayCreationExpr arrayCreation, CheckableArrayAccess arrayAccess
|
ArrayCreationExpr arrayCreation, CheckableArrayAccess arrayAccess
|
||||||
where
|
where
|
||||||
arrayAccess.canThrowOutOfBoundsDueToEmptyArray(sizeExpr, arrayCreation) and
|
arrayAccess.canThrowOutOfBoundsDueToEmptyArray(sizeExpr, arrayCreation) and
|
||||||
sizeExpr = sink.getNode().asExpr() and
|
sizeExpr = sink.getNode().asExpr() and
|
||||||
any(Conf conf).hasFlowPath(source, sink)
|
ImproperValidationOfArrayConstructionFlow::hasFlowPath(source, sink)
|
||||||
select arrayAccess.getIndexExpr(), source, sink,
|
select arrayAccess.getIndexExpr(), source, sink,
|
||||||
"This accesses the $@, but the array is initialized using a $@ which may be zero.", arrayCreation,
|
"This accesses the $@, but the array is initialized using a $@ which may be zero.", arrayCreation,
|
||||||
"array", source.getNode(), "user-provided value"
|
"array", source.getNode(), "user-provided value"
|
||||||
|
|||||||
@@ -13,30 +13,33 @@
|
|||||||
|
|
||||||
import java
|
import java
|
||||||
import ArraySizing
|
import ArraySizing
|
||||||
import DataFlow::PathGraph
|
import semmle.code.java.dataflow.TaintTracking
|
||||||
|
|
||||||
class BoundedFlowSourceConf extends DataFlow::Configuration {
|
module BoundedFlowSourceConfig implements DataFlow::ConfigSig {
|
||||||
BoundedFlowSourceConf() { this = "BoundedFlowSource" }
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
|
||||||
source instanceof BoundedFlowSource and
|
source instanceof BoundedFlowSource and
|
||||||
// There is not a fixed lower bound which is greater than zero.
|
// There is not a fixed lower bound which is greater than zero.
|
||||||
not source.(BoundedFlowSource).lowerBound() > 0
|
not source.(BoundedFlowSource).lowerBound() > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
predicate isSink(DataFlow::Node sink) {
|
||||||
any(CheckableArrayAccess caa).canThrowOutOfBoundsDueToEmptyArray(sink.asExpr(), _)
|
any(CheckableArrayAccess caa).canThrowOutOfBoundsDueToEmptyArray(sink.asExpr(), _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module BoundedFlowSourceFlow = DataFlow::Make<BoundedFlowSourceConfig>;
|
||||||
|
|
||||||
|
import BoundedFlowSourceFlow::PathGraph
|
||||||
|
|
||||||
from
|
from
|
||||||
DataFlow::PathNode source, DataFlow::PathNode sink, BoundedFlowSource boundedsource,
|
BoundedFlowSourceFlow::PathNode source, BoundedFlowSourceFlow::PathNode sink,
|
||||||
Expr sizeExpr, ArrayCreationExpr arrayCreation, CheckableArrayAccess arrayAccess
|
BoundedFlowSource boundedsource, Expr sizeExpr, ArrayCreationExpr arrayCreation,
|
||||||
|
CheckableArrayAccess arrayAccess
|
||||||
where
|
where
|
||||||
arrayAccess.canThrowOutOfBoundsDueToEmptyArray(sizeExpr, arrayCreation) and
|
arrayAccess.canThrowOutOfBoundsDueToEmptyArray(sizeExpr, arrayCreation) and
|
||||||
sizeExpr = sink.getNode().asExpr() and
|
sizeExpr = sink.getNode().asExpr() and
|
||||||
boundedsource = source.getNode() and
|
boundedsource = source.getNode() and
|
||||||
any(BoundedFlowSourceConf conf).hasFlowPath(source, sink)
|
BoundedFlowSourceFlow::hasFlowPath(source, sink)
|
||||||
select arrayAccess.getIndexExpr(), source, sink,
|
select arrayAccess.getIndexExpr(), source, sink,
|
||||||
"This accesses the $@, but the array is initialized using $@ which may be zero.", arrayCreation,
|
"This accesses the $@, but the array is initialized using $@ which may be zero.", arrayCreation,
|
||||||
"array", boundedsource, boundedsource.getDescription().toLowerCase()
|
"array", boundedsource, boundedsource.getDescription().toLowerCase()
|
||||||
|
|||||||
@@ -14,25 +14,28 @@
|
|||||||
import java
|
import java
|
||||||
import ArraySizing
|
import ArraySizing
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import DataFlow::PathGraph
|
|
||||||
|
|
||||||
class Conf extends TaintTracking::Configuration {
|
module ImproperValidationOfArrayConstructionLocalConfig implements DataFlow::ConfigSig {
|
||||||
Conf() { this = "LocalUserInputTocanThrowOutOfBoundsDueToEmptyArrayConfig" }
|
predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
any(CheckableArrayAccess caa).canThrowOutOfBoundsDueToEmptyArray(sink.asExpr(), _)
|
any(CheckableArrayAccess caa).canThrowOutOfBoundsDueToEmptyArray(sink.asExpr(), _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module ImproperValidationOfArrayConstructionLocalFlow =
|
||||||
|
TaintTracking::Make<ImproperValidationOfArrayConstructionLocalConfig>;
|
||||||
|
|
||||||
|
import ImproperValidationOfArrayConstructionLocalFlow::PathGraph
|
||||||
|
|
||||||
from
|
from
|
||||||
DataFlow::PathNode source, DataFlow::PathNode sink, Expr sizeExpr,
|
ImproperValidationOfArrayConstructionLocalFlow::PathNode source,
|
||||||
|
ImproperValidationOfArrayConstructionLocalFlow::PathNode sink, Expr sizeExpr,
|
||||||
ArrayCreationExpr arrayCreation, CheckableArrayAccess arrayAccess
|
ArrayCreationExpr arrayCreation, CheckableArrayAccess arrayAccess
|
||||||
where
|
where
|
||||||
arrayAccess.canThrowOutOfBoundsDueToEmptyArray(sizeExpr, arrayCreation) and
|
arrayAccess.canThrowOutOfBoundsDueToEmptyArray(sizeExpr, arrayCreation) and
|
||||||
sizeExpr = sink.getNode().asExpr() and
|
sizeExpr = sink.getNode().asExpr() and
|
||||||
any(Conf conf).hasFlowPath(source, sink)
|
ImproperValidationOfArrayConstructionLocalFlow::hasFlowPath(source, sink)
|
||||||
select arrayAccess.getIndexExpr(), source, sink,
|
select arrayAccess.getIndexExpr(), source, sink,
|
||||||
"This accesses the $@, but the array is initialized using a $@ which may be zero.", arrayCreation,
|
"This accesses the $@, but the array is initialized using a $@ which may be zero.", arrayCreation,
|
||||||
"array", source.getNode(), "user-provided value"
|
"array", source.getNode(), "user-provided value"
|
||||||
|
|||||||
@@ -13,24 +13,28 @@
|
|||||||
import java
|
import java
|
||||||
import ArraySizing
|
import ArraySizing
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import DataFlow::PathGraph
|
|
||||||
|
|
||||||
class Conf extends TaintTracking::Configuration {
|
module ImproperValidationOfArrayIndexConfig implements DataFlow::ConfigSig {
|
||||||
Conf() { this = "RemoteUserInputTocanThrowOutOfBoundsDueToEmptyArrayConfig" }
|
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
any(CheckableArrayAccess caa).canThrowOutOfBounds(sink.asExpr())
|
any(CheckableArrayAccess caa).canThrowOutOfBounds(sink.asExpr())
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) { node.getType() instanceof BooleanType }
|
predicate isBarrier(DataFlow::Node node) { node.getType() instanceof BooleanType }
|
||||||
}
|
}
|
||||||
|
|
||||||
from DataFlow::PathNode source, DataFlow::PathNode sink, CheckableArrayAccess arrayAccess
|
module ImproperValidationOfArrayIndexFlow =
|
||||||
|
TaintTracking::Make<ImproperValidationOfArrayIndexConfig>;
|
||||||
|
|
||||||
|
import ImproperValidationOfArrayIndexFlow::PathGraph
|
||||||
|
|
||||||
|
from
|
||||||
|
ImproperValidationOfArrayIndexFlow::PathNode source,
|
||||||
|
ImproperValidationOfArrayIndexFlow::PathNode sink, CheckableArrayAccess arrayAccess
|
||||||
where
|
where
|
||||||
arrayAccess.canThrowOutOfBounds(sink.getNode().asExpr()) and
|
arrayAccess.canThrowOutOfBounds(sink.getNode().asExpr()) and
|
||||||
any(Conf conf).hasFlowPath(source, sink)
|
ImproperValidationOfArrayIndexFlow::hasFlowPath(source, sink)
|
||||||
select arrayAccess.getIndexExpr(), source, sink,
|
select arrayAccess.getIndexExpr(), source, sink,
|
||||||
"This index depends on a $@ which can cause an ArrayIndexOutOfBoundsException.", source.getNode(),
|
"This index depends on a $@ which can cause an ArrayIndexOutOfBoundsException.", source.getNode(),
|
||||||
"user-provided value"
|
"user-provided value"
|
||||||
|
|||||||
@@ -14,25 +14,27 @@
|
|||||||
import java
|
import java
|
||||||
import ArraySizing
|
import ArraySizing
|
||||||
import BoundingChecks
|
import BoundingChecks
|
||||||
import DataFlow::PathGraph
|
import semmle.code.java.dataflow.TaintTracking
|
||||||
|
|
||||||
class BoundedFlowSourceConf extends DataFlow::Configuration {
|
module BoundedFlowSourceConfig implements DataFlow::ConfigSig {
|
||||||
BoundedFlowSourceConf() { this = "BoundedFlowSource" }
|
predicate isSource(DataFlow::Node source) { source instanceof BoundedFlowSource }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof BoundedFlowSource }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(CheckableArrayAccess arrayAccess | arrayAccess.canThrowOutOfBounds(sink.asExpr()))
|
exists(CheckableArrayAccess arrayAccess | arrayAccess.canThrowOutOfBounds(sink.asExpr()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module BoundedFlowSourceFlow = DataFlow::Make<BoundedFlowSourceConfig>;
|
||||||
|
|
||||||
|
import BoundedFlowSourceFlow::PathGraph
|
||||||
|
|
||||||
from
|
from
|
||||||
DataFlow::PathNode source, DataFlow::PathNode sink, BoundedFlowSource boundedsource,
|
BoundedFlowSourceFlow::PathNode source, BoundedFlowSourceFlow::PathNode sink,
|
||||||
CheckableArrayAccess arrayAccess
|
BoundedFlowSource boundedsource, CheckableArrayAccess arrayAccess
|
||||||
where
|
where
|
||||||
arrayAccess.canThrowOutOfBounds(sink.getNode().asExpr()) and
|
arrayAccess.canThrowOutOfBounds(sink.getNode().asExpr()) and
|
||||||
boundedsource = source.getNode() and
|
boundedsource = source.getNode() and
|
||||||
any(BoundedFlowSourceConf conf).hasFlowPath(source, sink) and
|
BoundedFlowSourceFlow::hasFlowPath(source, sink) and
|
||||||
boundedsource != sink.getNode() and
|
boundedsource != sink.getNode() and
|
||||||
not (
|
not (
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -14,22 +14,26 @@
|
|||||||
import java
|
import java
|
||||||
import ArraySizing
|
import ArraySizing
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import DataFlow::PathGraph
|
|
||||||
|
|
||||||
class Conf extends TaintTracking::Configuration {
|
module ImproperValidationOfArrayIndexLocalConfig implements DataFlow::ConfigSig {
|
||||||
Conf() { this = "LocalUserInputTocanThrowOutOfBoundsDueToEmptyArrayConfig" }
|
predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
any(CheckableArrayAccess caa).canThrowOutOfBounds(sink.asExpr())
|
any(CheckableArrayAccess caa).canThrowOutOfBounds(sink.asExpr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from DataFlow::PathNode source, DataFlow::PathNode sink, CheckableArrayAccess arrayAccess
|
module ImproperValidationOfArrayIndexLocalFlow =
|
||||||
|
TaintTracking::Make<ImproperValidationOfArrayIndexLocalConfig>;
|
||||||
|
|
||||||
|
import ImproperValidationOfArrayIndexLocalFlow::PathGraph
|
||||||
|
|
||||||
|
from
|
||||||
|
ImproperValidationOfArrayIndexLocalFlow::PathNode source,
|
||||||
|
ImproperValidationOfArrayIndexLocalFlow::PathNode sink, CheckableArrayAccess arrayAccess
|
||||||
where
|
where
|
||||||
arrayAccess.canThrowOutOfBounds(sink.getNode().asExpr()) and
|
arrayAccess.canThrowOutOfBounds(sink.getNode().asExpr()) and
|
||||||
any(Conf conf).hasFlowPath(source, sink)
|
ImproperValidationOfArrayIndexLocalFlow::hasFlowPath(source, sink)
|
||||||
select arrayAccess.getIndexExpr(), source, sink,
|
select arrayAccess.getIndexExpr(), source, sink,
|
||||||
"This index depends on a $@ which can cause an ArrayIndexOutOfBoundsException.", source.getNode(),
|
"This index depends on a $@ which can cause an ArrayIndexOutOfBoundsException.", source.getNode(),
|
||||||
"user-provided value"
|
"user-provided value"
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class ExtremeSource extends VarAccess {
|
|||||||
ExtremeSource() { this.getVariable() instanceof ExtremeValueField }
|
ExtremeSource() { this.getVariable() instanceof ExtremeValueField }
|
||||||
}
|
}
|
||||||
|
|
||||||
private module MaxValueFlowConfig implements DataFlow::ConfigSig {
|
module MaxValueFlowConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node source) {
|
predicate isSource(DataFlow::Node source) {
|
||||||
source.asExpr().(ExtremeSource).getVariable() instanceof MaxValueField
|
source.asExpr().(ExtremeSource).getVariable() instanceof MaxValueField
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ private module MaxValueFlowConfig implements DataFlow::ConfigSig {
|
|||||||
|
|
||||||
module MaxValueFlow = DataFlow::Make<MaxValueFlowConfig>;
|
module MaxValueFlow = DataFlow::Make<MaxValueFlowConfig>;
|
||||||
|
|
||||||
private module MinValueFlowConfig implements DataFlow::ConfigSig {
|
module MinValueFlowConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node source) {
|
predicate isSource(DataFlow::Node source) {
|
||||||
source.asExpr().(ExtremeSource).getVariable() instanceof MinValueField
|
source.asExpr().(ExtremeSource).getVariable() instanceof MinValueField
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,22 +120,20 @@ class GetMessageFlowSource extends MethodAccess {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GetMessageFlowSourceToHttpResponseSinkFlowConfig extends TaintTracking::Configuration {
|
module GetMessageFlowSourceToHttpResponseSinkFlowConfig implements DataFlow::ConfigSig {
|
||||||
GetMessageFlowSourceToHttpResponseSinkFlowConfig() {
|
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof GetMessageFlowSource }
|
||||||
this = "StackTraceExposure::GetMessageFlowSourceToHttpResponseSinkFlowConfig"
|
|
||||||
|
predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink }
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof GetMessageFlowSource }
|
module GetMessageFlowSourceToHttpResponseSinkFlow =
|
||||||
|
TaintTracking::Make<GetMessageFlowSourceToHttpResponseSinkFlowConfig>;
|
||||||
override predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A call to `getMessage()` that then flows to a servlet response.
|
* A call to `getMessage()` that then flows to a servlet response.
|
||||||
*/
|
*/
|
||||||
predicate getMessageFlowsExternally(DataFlow::Node externalExpr, GetMessageFlowSource getMessage) {
|
predicate getMessageFlowsExternally(DataFlow::Node externalExpr, GetMessageFlowSource getMessage) {
|
||||||
any(GetMessageFlowSourceToHttpResponseSinkFlowConfig conf)
|
GetMessageFlowSourceToHttpResponseSinkFlow::hasFlow(DataFlow::exprNode(getMessage), externalExpr)
|
||||||
.hasFlow(DataFlow::exprNode(getMessage), externalExpr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
from Expr externalExpr, Expr errorInformation
|
from Expr externalExpr, Expr errorInformation
|
||||||
|
|||||||
@@ -26,10 +26,8 @@ predicate isSafeSecureCookieSetting(Expr e) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class SecureCookieConfiguration extends DataFlow::Configuration {
|
module SecureCookieConfig implements DataFlow::ConfigSig {
|
||||||
SecureCookieConfiguration() { this = "SecureCookieConfiguration" }
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
|
||||||
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
||||||
m.getDeclaringType() instanceof TypeCookie and
|
m.getDeclaringType() instanceof TypeCookie and
|
||||||
m.getName() = "setSecure" and
|
m.getName() = "setSecure" and
|
||||||
@@ -43,14 +41,16 @@ class SecureCookieConfiguration extends DataFlow::Configuration {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
predicate isSink(DataFlow::Node sink) {
|
||||||
sink.asExpr() =
|
sink.asExpr() =
|
||||||
any(MethodAccess add | add.getMethod() instanceof ResponseAddCookieMethod).getArgument(0)
|
any(MethodAccess add | add.getMethod() instanceof ResponseAddCookieMethod).getArgument(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module SecureCookieFlow = DataFlow::Make<SecureCookieConfig>;
|
||||||
|
|
||||||
from MethodAccess add
|
from MethodAccess add
|
||||||
where
|
where
|
||||||
add.getMethod() instanceof ResponseAddCookieMethod and
|
add.getMethod() instanceof ResponseAddCookieMethod and
|
||||||
not any(SecureCookieConfiguration df).hasFlowToExpr(add.getArgument(0))
|
not SecureCookieFlow::hasFlowToExpr(add.getArgument(0))
|
||||||
select add, "Cookie is added to response without the 'secure' flag being set."
|
select add, "Cookie is added to response without the 'secure' flag being set."
|
||||||
|
|||||||
Reference in New Issue
Block a user