Python: Rewrite logic to split on nomalization

This commit is contained in:
Rasmus Lerchedahl Petersen
2020-10-22 11:35:55 +02:00
parent 391925532d
commit 8549c9cfde

View File

@@ -25,9 +25,9 @@ import experimental.semmle.python.Concepts
import experimental.dataflow.RemoteFlowSources
import DataFlow::PathGraph
/** Configuration to find paths from sources to sinks that contain no checks. */
class UncheckedPathConfiguration extends TaintTracking::Configuration {
UncheckedPathConfiguration() { this = "UncheckedPathConfiguration" }
/** Configuration to find paths from sources to sinks that contain no normalization. */
class UnNormalizedPathConfiguration extends TaintTracking::Configuration {
UnNormalizedPathConfiguration() { this = "UnNormalizedPathConfiguration" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
@@ -35,25 +35,25 @@ class UncheckedPathConfiguration extends TaintTracking::Configuration {
sink = any(FileSystemAccess e).getAPathArgument()
}
override predicate isSanitizer(DataFlow::Node node) { node instanceof PathCheck }
}
/** Configuration to find paths from sources to checks that contain no normalization. */
class CheckUnnormalizedConfiguration extends TaintTracking2::Configuration {
CheckUnnormalizedConfiguration() { this = "CheckUnnormalizedConfiguration" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof PathCheck }
override predicate isSanitizer(DataFlow::Node node) { node instanceof PathNormalization }
}
class CheckUnnormalized extends DataFlow2::PathNode {
/** Configuration to find paths from sources to normalizations that contain no prior normalizations. */
class FirstNormalizationConfiguration extends TaintTracking2::Configuration {
FirstNormalizationConfiguration() { this = "FirstNormalizationConfiguration" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof PathNormalization }
override predicate isSanitizerOut(DataFlow::Node node) { node instanceof PathNormalization }
}
class FirstNormalization extends DataFlow2::PathNode {
DataFlow::Node sourceNode;
CheckUnnormalized() {
exists(CheckUnnormalizedConfiguration conf, DataFlow2::PathNode source |
FirstNormalization() {
exists(FirstNormalizationConfiguration conf, DataFlow2::PathNode source |
sourceNode = source.getNode() and
conf.hasFlowPath(source, this)
)
@@ -62,32 +62,35 @@ class CheckUnnormalized extends DataFlow2::PathNode {
DataFlow::Node getSourceNode() { result = sourceNode }
}
/** Configuration to find paths from checks to sinks that contain no further checks. */
class LastCheckConfiguration extends TaintTracking::Configuration {
LastCheckConfiguration() { this = "UncheckedPathConfiguration" }
/** Configuration to find paths from normalizations to sinks that do not go through a check. */
class UncheckedNormalizedConfiguration extends TaintTracking::Configuration {
UncheckedNormalizedConfiguration() { this = "UncheckedNormalizedConfiguration" }
override predicate isSource(DataFlow::Node source) {
source = any(CheckUnnormalized cu).getNode()
}
override predicate isSource(DataFlow::Node source) { source instanceof PathNormalization }
override predicate isSink(DataFlow::Node sink) {
sink = any(FileSystemAccess e).getAPathArgument()
}
override predicate isSanitizer(DataFlow::Node node) { node instanceof PathCheck }
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { guard instanceof PathCheck }
}
from TaintTracking::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where
// Path has no check on it.
config instanceof UncheckedPathConfiguration and
// Path has no normalization on it.
config instanceof UnNormalizedPathConfiguration and
config.hasFlowPath(source, sink)
or
// Path has a check on it, but no prior normalization.
config instanceof LastCheckConfiguration and
exists(DataFlow::PathNode c, CheckUnnormalized cu | cu.getNode() = c.getNode() |
// Path has a normalization on it, but no subsequent check.
config instanceof UncheckedNormalizedConfiguration and
config.hasFlowPath(source, sink)
or
// This should report a better source, but does not quite work.
// Path has a normalization on it, but no subsequent check.
config instanceof UncheckedNormalizedConfiguration and
exists(DataFlow::PathNode c, FirstNormalization n | n.getNode() = c.getNode() |
config.hasFlowPath(c, sink) and
source.getNode() = cu.getSourceNode()
source.getNode() = n.getSourceNode()
)
select sink.getNode(), source, sink, "This path depends on $@.", source.getNode(),
"a user-provided value"