1
- /** Provides class and predicates to track external data that
1
+ /**
2
+ * Provides class and predicates to track external data that
2
3
* may represent malicious OS commands.
3
4
*
4
5
* This module is intended to be imported into a taint-tracking query
5
6
* to extend `TaintKind` and `TaintSink`.
6
- *
7
7
*/
8
- import python
9
8
9
+ import python
10
10
import semmle.python.security.TaintTracking
11
11
import semmle.python.security.strings.Untrusted
12
12
@@ -19,8 +19,7 @@ private ModuleObject osOrPopenModule() {
19
19
}
20
20
21
21
private Object makeOsCall ( ) {
22
- exists ( string name |
23
- result = ModuleObject:: named ( "subprocess" ) .attr ( name ) |
22
+ exists ( string name | result = ModuleObject:: named ( "subprocess" ) .attr ( name ) |
24
23
name = "Popen" or
25
24
name = "call" or
26
25
name = "check_call" or
@@ -31,40 +30,27 @@ private Object makeOsCall() {
31
30
32
31
/**Special case for first element in sequence. */
33
32
class FirstElementKind extends TaintKind {
33
+ FirstElementKind ( ) { this = "sequence[" + any ( ExternalStringKind key ) + "][0]" }
34
34
35
- FirstElementKind ( ) {
36
- this = "sequence[" + any ( ExternalStringKind key ) + "][0]"
37
- }
38
-
39
- override string repr ( ) {
40
- result = "first item in sequence of " + this .getItem ( ) .repr ( )
41
- }
35
+ override string repr ( ) { result = "first item in sequence of " + this .getItem ( ) .repr ( ) }
42
36
43
37
/** Gets the taint kind for item in this sequence. */
44
- ExternalStringKind getItem ( ) {
45
- this = "sequence[" + result + "][0]"
46
- }
47
-
38
+ ExternalStringKind getItem ( ) { this = "sequence[" + result + "][0]" }
48
39
}
49
40
50
41
class FirstElementFlow extends DataFlowExtension:: DataFlowNode {
42
+ FirstElementFlow ( ) { this = any ( SequenceNode s ) .getElement ( 0 ) }
51
43
52
- FirstElementFlow ( ) {
53
- this = any ( SequenceNode s ) .getElement ( 0 )
54
- }
55
-
56
- override
57
- ControlFlowNode getASuccessorNode ( TaintKind fromkind , TaintKind tokind ) {
44
+ override ControlFlowNode getASuccessorNode ( TaintKind fromkind , TaintKind tokind ) {
58
45
result .( SequenceNode ) .getElement ( 0 ) = this and tokind .( FirstElementKind ) .getItem ( ) = fromkind
59
46
}
60
-
61
47
}
62
48
63
- /** A taint sink that is potentially vulnerable to malicious shell commands.
49
+ /**
50
+ * A taint sink that is potentially vulnerable to malicious shell commands.
64
51
* The `vuln` in `subprocess.call(shell=vuln)` and similar calls.
65
52
*/
66
53
class ShellCommand extends CommandSink {
67
-
68
54
override string toString ( ) { result = "shell command" }
69
55
70
56
ShellCommand ( ) {
@@ -77,7 +63,8 @@ class ShellCommand extends CommandSink {
77
63
or
78
64
exists ( CallNode call , string name |
79
65
call .getAnArg ( ) = this and
80
- call .getFunction ( ) .refersTo ( osOrPopenModule ( ) .attr ( name ) ) |
66
+ call .getFunction ( ) .refersTo ( osOrPopenModule ( ) .attr ( name ) )
67
+ |
81
68
name = "system" or
82
69
name = "popen" or
83
70
name .matches ( "popen_" )
@@ -96,19 +83,18 @@ class ShellCommand extends CommandSink {
96
83
/* List (or tuple) containing a tainted string command */
97
84
kind instanceof ExternalStringSequenceKind
98
85
}
99
-
100
86
}
101
87
102
- /** A taint sink that is potentially vulnerable to malicious shell commands.
88
+ /**
89
+ * A taint sink that is potentially vulnerable to malicious shell commands.
103
90
* The `vuln` in `subprocess.call(vuln, ...)` and similar calls.
104
91
*/
105
92
class OsCommandFirstArgument extends CommandSink {
106
-
107
93
override string toString ( ) { result = "OS command first argument" }
108
94
109
95
OsCommandFirstArgument ( ) {
110
96
not this instanceof ShellCommand and
111
- exists ( CallNode call |
97
+ exists ( CallNode call |
112
98
call .getFunction ( ) .refersTo ( makeOsCall ( ) ) and
113
99
call .getArg ( 0 ) = this
114
100
)
@@ -121,7 +107,6 @@ class OsCommandFirstArgument extends CommandSink {
121
107
/* List (or tuple) whose first element is tainted */
122
108
kind instanceof FirstElementKind
123
109
}
124
-
125
110
}
126
111
127
112
// -------------------------------------------------------------------------- //
@@ -130,8 +115,8 @@ class OsCommandFirstArgument extends CommandSink {
130
115
// Since fabric build so closely upon invoke, we model them together to avoid
131
116
// duplication
132
117
// -------------------------------------------------------------------------- //
133
-
134
- /* * A taint sink that is potentially vulnerable to malicious shell commands.
118
+ /**
119
+ * A taint sink that is potentially vulnerable to malicious shell commands.
135
120
* The `vuln` in `invoke.run(vuln, ...)` and similar calls.
136
121
*/
137
122
class InvokeRun extends CommandSink {
@@ -143,12 +128,11 @@ class InvokeRun extends CommandSink {
143
128
144
129
override string toString ( ) { result = "InvokeRun" }
145
130
146
- override predicate sinks ( TaintKind kind ) {
147
- kind instanceof ExternalStringKind
148
- }
131
+ override predicate sinks ( TaintKind kind ) { kind instanceof ExternalStringKind }
149
132
}
150
133
151
- /** Internal TaintKind to track the invoke.Context instance passed to functions
134
+ /**
135
+ * Internal TaintKind to track the invoke.Context instance passed to functions
152
136
* marked with @invoke.task
153
137
*/
154
138
private class InvokeContextArg extends TaintKind {
@@ -164,7 +148,6 @@ private class InvokeContextArgSource extends TaintSource {
164
148
decorator = f .getADecorator ( ) and not decorator instanceof Call
165
149
or
166
150
decorator = f .getADecorator ( ) .( Call ) .getFunc ( )
167
-
168
151
) and
169
152
(
170
153
decorator .pointsTo ( Value:: named ( "invoke.task" ) )
@@ -176,12 +159,11 @@ private class InvokeContextArgSource extends TaintSource {
176
159
)
177
160
}
178
161
179
- override predicate isSourceOf ( TaintKind kind ) {
180
- kind instanceof InvokeContextArg
181
- }
162
+ override predicate isSourceOf ( TaintKind kind ) { kind instanceof InvokeContextArg }
182
163
}
183
164
184
- /** A taint sink that is potentially vulnerable to malicious shell commands.
165
+ /**
166
+ * A taint sink that is potentially vulnerable to malicious shell commands.
185
167
* The `vuln` in `invoke.Context().run(vuln, ...)` and similar calls.
186
168
*/
187
169
class InvokeContextRun extends CommandSink {
@@ -195,7 +177,8 @@ class InvokeContextRun extends CommandSink {
195
177
// since fabric.Connection.run has a decorator, it doesn't work with FunctionValue :|
196
178
// and `Value::named("fabric.Connection").(ClassValue).lookup("run").getACall()` returned no results,
197
179
// so here is the hacky solution that works :\
198
- call .getFunction ( ) .( AttrNode ) .getObject ( "run" ) .pointsTo ( ) .getClass ( ) = Value:: named ( "fabric.Connection" )
180
+ call .getFunction ( ) .( AttrNode ) .getObject ( "run" ) .pointsTo ( ) .getClass ( ) =
181
+ Value:: named ( "fabric.Connection" )
199
182
|
200
183
this = call .getArg ( 0 )
201
184
or
@@ -205,38 +188,33 @@ class InvokeContextRun extends CommandSink {
205
188
206
189
override string toString ( ) { result = "InvokeContextRun" }
207
190
208
- override predicate sinks ( TaintKind kind ) {
209
- kind instanceof ExternalStringKind
210
- }
191
+ override predicate sinks ( TaintKind kind ) { kind instanceof ExternalStringKind }
211
192
}
212
193
213
- /** A taint sink that is potentially vulnerable to malicious shell commands.
194
+ /**
195
+ * A taint sink that is potentially vulnerable to malicious shell commands.
214
196
* The `vuln` in `fabric.Group().run(vuln, ...)` and similar calls.
215
197
*/
216
198
class FabricGroupRun extends CommandSink {
217
199
FabricGroupRun ( ) {
218
200
exists ( ClassValue cls |
219
- cls .getASuperType ( ) = Value:: named ( "fabric.Group" ) and
201
+ cls .getASuperType ( ) = Value:: named ( "fabric.Group" ) and
220
202
this = cls .lookup ( "run" ) .( FunctionValue ) .getArgumentForCall ( _, 1 )
221
203
)
222
204
}
223
205
224
206
override string toString ( ) { result = "FabricGroupRun" }
225
207
226
- override predicate sinks ( TaintKind kind ) {
227
- kind instanceof ExternalStringKind
228
- }
208
+ override predicate sinks ( TaintKind kind ) { kind instanceof ExternalStringKind }
229
209
}
230
210
231
-
232
211
// -------------------------------------------------------------------------- //
233
212
// Modeling of the 'invoke' package and 'fabric' package (v 1.x)
234
213
// -------------------------------------------------------------------------- //
235
214
class FabricV1Commands extends CommandSink {
236
215
FabricV1Commands ( ) {
237
216
// since `run` and `sudo` are decorated, we can't use FunctionValue's :(
238
- exists ( CallNode call
239
- |
217
+ exists ( CallNode call |
240
218
call = Value:: named ( "fabric.api.local" ) .getACall ( )
241
219
or
242
220
call = Value:: named ( "fabric.api.run" ) .getACall ( )
@@ -251,7 +229,5 @@ class FabricV1Commands extends CommandSink {
251
229
252
230
override string toString ( ) { result = "FabricV1Commands" }
253
231
254
- override predicate sinks ( TaintKind kind ) {
255
- kind instanceof ExternalStringKind
256
- }
232
+ override predicate sinks ( TaintKind kind ) { kind instanceof ExternalStringKind }
257
233
}
0 commit comments