2
2
* Provides taint-tracking configurations for detecting "path injection" vulnerabilities.
3
3
*
4
4
* Note, for performance reasons: only import this file if
5
- * the Configurations or the `pathInjection` predicate are needed, otherwise
5
+ * `PathInjection::Configuration` is needed, otherwise
6
6
* `PathInjectionCustomizations` should be imported instead.
7
7
*/
8
8
9
9
private import python
10
10
private import semmle.python.Concepts
11
- private import semmle.python.dataflow.new.DataFlow
11
+ import semmle.python.dataflow.new.DataFlow
12
+ import semmle.python.dataflow.new.TaintTracking
13
+
14
+ /**
15
+ * Provides a taint-tracking configuration for detecting "path injection" vulnerabilities.
16
+ */
17
+ module PathInjection {
18
+ import PathInjectionCustomizations:: PathInjection
19
+
20
+ /**
21
+ * A taint-tracking configuration for detecting "path injection" vulnerabilities.
22
+ *
23
+ * This configuration uses two flow states, `NotNormalized` and `NormalizedUnchecked`,
24
+ * to track the requirement that a file path must be first normalized and then checked
25
+ * before it is safe to use.
26
+ *
27
+ * At sources, paths are assumed not normalized. At normalization points, they change
28
+ * state to `NormalizedUnchecked` after which they can be made safe by an appropriate
29
+ * check of the prefix.
30
+ *
31
+ * Such checks are ineffective in the `NotNormalized` state.
32
+ */
33
+ class Configuration extends TaintTracking:: Configuration {
34
+ Configuration ( ) { this = "PathInjection" }
35
+
36
+ override predicate isSource ( DataFlow:: Node source , DataFlow:: FlowState state ) {
37
+ source instanceof Source and state instanceof NotNormalized
38
+ }
39
+
40
+ override predicate isSink ( DataFlow:: Node sink , DataFlow:: FlowState state ) {
41
+ sink instanceof Sink and
42
+ (
43
+ state instanceof NotNormalized or
44
+ state instanceof NormalizedUnchecked
45
+ )
46
+ }
47
+
48
+ override predicate isSanitizer ( DataFlow:: Node node ) { node instanceof Sanitizer }
49
+
50
+ override predicate isBarrier ( DataFlow:: Node node , DataFlow:: FlowState state ) {
51
+ // Block `NotNormalized` paths here, since they change state to `NormalizedUnchecked`
52
+ node instanceof Path:: PathNormalization and
53
+ state instanceof NotNormalized
54
+ or
55
+ node = any ( Path:: SafeAccessCheck c ) .getAGuardedNode ( ) and
56
+ state instanceof NormalizedUnchecked
57
+ }
58
+
59
+ override predicate isSanitizerGuard ( DataFlow:: BarrierGuard guard ) {
60
+ guard instanceof SanitizerGuard
61
+ }
62
+
63
+ override predicate isAdditionalFlowStep (
64
+ DataFlow:: Node nodeFrom , DataFlow:: FlowState stateFrom , DataFlow:: Node nodeTo ,
65
+ DataFlow:: FlowState stateTo
66
+ ) {
67
+ nodeFrom = nodeTo .( Path:: PathNormalization ) .getPathArg ( ) and
68
+ stateFrom instanceof NotNormalized and
69
+ stateTo instanceof NormalizedUnchecked
70
+ }
71
+ }
72
+
73
+ /** A state signifying that the file path has not been normalized. */
74
+ class NotNormalized extends DataFlow:: FlowState {
75
+ NotNormalized ( ) { this = "NotNormalized" }
76
+ }
77
+
78
+ /** A state signifying that the file path has been normalized, but not checked. */
79
+ class NormalizedUnchecked extends DataFlow:: FlowState {
80
+ NormalizedUnchecked ( ) { this = "NormalizedUnchecked" }
81
+ }
82
+ }
83
+
84
+ // ---------------------------------------------------------------------------
85
+ // Old, deprecated code
86
+ // ---------------------------------------------------------------------------
12
87
private import semmle.python.dataflow.new.DataFlow2
13
- private import semmle.python.dataflow.new.TaintTracking
14
88
private import semmle.python.dataflow.new.TaintTracking2
15
- import ChainedConfigs12
89
+ private import ChainedConfigs12
16
90
import PathInjectionCustomizations:: PathInjection
17
91
18
92
// ---------------------------------------------------------------------------
19
93
// Case 1. The path is never normalized.
20
94
// ---------------------------------------------------------------------------
21
- /** Configuration to find paths from sources to sinks that contain no normalization. */
22
- class PathNotNormalizedConfiguration extends TaintTracking:: Configuration {
95
+ /**
96
+ * DEPRECATED: Use `PathInjection::Configuration` instead
97
+ *
98
+ * Configuration to find paths from sources to sinks that contain no normalization.
99
+ */
100
+ deprecated class PathNotNormalizedConfiguration extends TaintTracking:: Configuration {
23
101
PathNotNormalizedConfiguration ( ) { this = "PathNotNormalizedConfiguration" }
24
102
25
103
override predicate isSource ( DataFlow:: Node source ) { source instanceof Source }
@@ -38,18 +116,24 @@ class PathNotNormalizedConfiguration extends TaintTracking::Configuration {
38
116
}
39
117
40
118
/**
119
+ * DEPRECATED: Use `PathInjection::Configuration` instead
120
+ *
41
121
* Holds if there is a path injection from source to sink, where the (python) path is
42
122
* not normalized.
43
123
*/
44
- predicate pathNotNormalized ( CustomPathNode source , CustomPathNode sink ) {
124
+ deprecated predicate pathNotNormalized ( CustomPathNode source , CustomPathNode sink ) {
45
125
any ( PathNotNormalizedConfiguration config ) .hasFlowPath ( source .asNode1 ( ) , sink .asNode1 ( ) )
46
126
}
47
127
48
128
// ---------------------------------------------------------------------------
49
129
// Case 2. The path is normalized at least once, but never checked afterwards.
50
130
// ---------------------------------------------------------------------------
51
- /** Configuration to find paths from sources to normalizations that contain no prior normalizations. */
52
- class FirstNormalizationConfiguration extends TaintTracking:: Configuration {
131
+ /**
132
+ * DEPRECATED: Use `PathInjection::Configuration` instead
133
+ *
134
+ * Configuration to find paths from sources to normalizations that contain no prior normalizations.
135
+ */
136
+ deprecated class FirstNormalizationConfiguration extends TaintTracking:: Configuration {
53
137
FirstNormalizationConfiguration ( ) { this = "FirstNormalizationConfiguration" }
54
138
55
139
override predicate isSource ( DataFlow:: Node source ) { source instanceof Source }
@@ -65,8 +149,12 @@ class FirstNormalizationConfiguration extends TaintTracking::Configuration {
65
149
}
66
150
}
67
151
68
- /** Configuration to find paths from normalizations to sinks that do not go through a check. */
69
- class NormalizedPathNotCheckedConfiguration extends TaintTracking2:: Configuration {
152
+ /**
153
+ * DEPRECATED: Use `PathInjection::Configuration` instead
154
+ *
155
+ * Configuration to find paths from normalizations to sinks that do not go through a check.
156
+ */
157
+ deprecated class NormalizedPathNotCheckedConfiguration extends TaintTracking2:: Configuration {
70
158
NormalizedPathNotCheckedConfiguration ( ) { this = "NormalizedPathNotCheckedConfiguration" }
71
159
72
160
override predicate isSource ( DataFlow:: Node source ) { source instanceof Path:: PathNormalization }
@@ -83,10 +171,12 @@ class NormalizedPathNotCheckedConfiguration extends TaintTracking2::Configuratio
83
171
}
84
172
85
173
/**
174
+ * DEPRECATED: Use `PathInjection::Configuration` instead
175
+ *
86
176
* Holds if there is a path injection from source to sink, where the (python) path is
87
177
* normalized at least once, but never checked afterwards.
88
178
*/
89
- predicate pathNotCheckedAfterNormalization ( CustomPathNode source , CustomPathNode sink ) {
179
+ deprecated predicate pathNotCheckedAfterNormalization ( CustomPathNode source , CustomPathNode sink ) {
90
180
exists (
91
181
FirstNormalizationConfiguration config , DataFlow:: PathNode mid1 , DataFlow2:: PathNode mid2 ,
92
182
NormalizedPathNotCheckedConfiguration config2
@@ -100,8 +190,12 @@ predicate pathNotCheckedAfterNormalization(CustomPathNode source, CustomPathNode
100
190
// ---------------------------------------------------------------------------
101
191
// Query: Either case 1 or case 2.
102
192
// ---------------------------------------------------------------------------
103
- /** Holds if there is a path injection from source to sink */
104
- predicate pathInjection ( CustomPathNode source , CustomPathNode sink ) {
193
+ /**
194
+ * DEPRECATED: Use `PathInjection::Configuration` instead
195
+ *
196
+ * Holds if there is a path injection from source to sink
197
+ */
198
+ deprecated predicate pathInjection ( CustomPathNode source , CustomPathNode sink ) {
105
199
pathNotNormalized ( source , sink )
106
200
or
107
201
pathNotCheckedAfterNormalization ( source , sink )
0 commit comments