mirror of
https://github.com/github/codeql.git
synced 2025-12-20 10:46:30 +01:00
Python: Rewrite logic to split on nomalization
This commit is contained in:
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user