11/**
2- * Provides a taint-tracking configuration for detecting path injection
3- * vulnerabilities.
2+ * Provides taint-tracking configurations for detecting "path injection" vulnerabilities.
43 *
5- * We detect cases where a user-controlled path is used in an unsafe manner,
6- * meaning it is not both normalized and _afterwards_ checked.
7- *
8- * It does so by dividing the problematic situation into two cases:
9- * 1. The file path is never normalized.
10- * This is easily detected by using normalization as a sanitizer.
11- *
12- * 2. The file path is normalized at least once, but never checked afterwards.
13- * This is detected by finding the earliest normalization and then ensuring that
14- * no checks happen later. Since we start from the earliest normalization,
15- * we know that the absence of checks means that no normalization has a
16- * check after it. (No checks after a second normalization would be ok if
17- * there was a check between the first and the second.)
18- *
19- * Note that one could make the dual split on whether the file path is ever checked. This does
20- * not work as nicely, however, since checking is modelled as a `BarrierGuard` rather than
21- * as a `Sanitizer`. That means that only some dataflow paths out of a check will be removed,
22- * and so identifying the last check is not possible simply by finding a dataflow path from it
23- * to a sink.
4+ * Note, for performance reasons: only import this file if
5+ * the Configurations or the `pathInjection` predicate are needed, otherwise
6+ * `PathInjectionCustomizations` should be imported instead.
247 */
258
26- import python
27- import semmle.python.dataflow.new.DataFlow
28- import semmle.python.dataflow.new.DataFlow2
29- import semmle.python.dataflow.new.TaintTracking
30- import semmle.python.dataflow.new.TaintTracking2
31- import semmle.python.Concepts
32- import semmle.python.dataflow.new.RemoteFlowSources
9+ private import python
10+ private import semmle.python.Concepts
11+ private import semmle.python.dataflow.new.DataFlow
12+ private import semmle.python.dataflow.new.DataFlow2
13+ private import semmle.python.dataflow.new.TaintTracking
14+ private import semmle.python.dataflow.new.TaintTracking2
3315import ChainedConfigs12
34- import semmle.python.dataflow.new.BarrierGuards
16+ import PathInjectionCustomizations :: PathInjection
3517
3618// ---------------------------------------------------------------------------
3719// Case 1. The path is never normalized.
@@ -40,16 +22,14 @@ import semmle.python.dataflow.new.BarrierGuards
4022class PathNotNormalizedConfiguration extends TaintTracking:: Configuration {
4123 PathNotNormalizedConfiguration ( ) { this = "PathNotNormalizedConfiguration" }
4224
43- override predicate isSource ( DataFlow:: Node source ) { source instanceof RemoteFlowSource }
25+ override predicate isSource ( DataFlow:: Node source ) { source instanceof Source }
4426
45- override predicate isSink ( DataFlow:: Node sink ) {
46- sink = any ( FileSystemAccess e ) .getAPathArgument ( )
47- }
27+ override predicate isSink ( DataFlow:: Node sink ) { sink instanceof Sink }
4828
4929 override predicate isSanitizer ( DataFlow:: Node node ) { node instanceof Path:: PathNormalization }
5030
5131 override predicate isSanitizerGuard ( DataFlow:: BarrierGuard guard ) {
52- guard instanceof StringConstCompare
32+ guard instanceof SanitizerGuard
5333 }
5434}
5535
@@ -68,14 +48,14 @@ predicate pathNotNormalized(CustomPathNode source, CustomPathNode sink) {
6848class FirstNormalizationConfiguration extends TaintTracking:: Configuration {
6949 FirstNormalizationConfiguration ( ) { this = "FirstNormalizationConfiguration" }
7050
71- override predicate isSource ( DataFlow:: Node source ) { source instanceof RemoteFlowSource }
51+ override predicate isSource ( DataFlow:: Node source ) { source instanceof Source }
7252
7353 override predicate isSink ( DataFlow:: Node sink ) { sink instanceof Path:: PathNormalization }
7454
7555 override predicate isSanitizerOut ( DataFlow:: Node node ) { node instanceof Path:: PathNormalization }
7656
7757 override predicate isSanitizerGuard ( DataFlow:: BarrierGuard guard ) {
78- guard instanceof StringConstCompare
58+ guard instanceof SanitizerGuard
7959 }
8060}
8161
@@ -85,14 +65,12 @@ class NormalizedPathNotCheckedConfiguration extends TaintTracking2::Configuratio
8565
8666 override predicate isSource ( DataFlow:: Node source ) { source instanceof Path:: PathNormalization }
8767
88- override predicate isSink ( DataFlow:: Node sink ) {
89- sink = any ( FileSystemAccess e ) .getAPathArgument ( )
90- }
68+ override predicate isSink ( DataFlow:: Node sink ) { sink instanceof Sink }
9169
9270 override predicate isSanitizerGuard ( DataFlow:: BarrierGuard guard ) {
9371 guard instanceof Path:: SafeAccessCheck
9472 or
95- guard instanceof StringConstCompare
73+ guard instanceof SanitizerGuard
9674 }
9775}
9876
0 commit comments