7
7
* query.
8
8
*/
9
9
10
- import semmle.code.java.dataflow.FlowSources
11
- import semmle.code.java.security.ExternalProcess
12
- import semmle.code.java.security.CommandArguments
10
+ import java
11
+ private import semmle.code.java.dataflow.FlowSources
12
+ private import semmle.code.java.dataflow.ExternalFlow
13
+ private import semmle.code.java.security.ExternalProcess
14
+ private import semmle.code.java.security.CommandArguments
15
+
16
+ /** A sink for command injection vulnerabilities. */
17
+ abstract class CommandInjectionSink extends DataFlow:: Node { }
18
+
19
+ /** A sanitizer for command injection vulnerabilities. */
20
+ abstract class CommandInjectionSanitizer extends DataFlow:: Node { }
13
21
14
22
/**
15
- * DEPRECATED: Use `RemoteUserInputToArgumentToExecFlow` instead .
23
+ * A unit class for adding additional taint steps .
16
24
*
17
- * A taint-tracking configuration for unvalidated user input that is used to run an external process .
25
+ * Extend this class to add additional taint steps that should apply to configurations related to command injection .
18
26
*/
19
- deprecated class RemoteUserInputToArgumentToExecFlowConfig extends TaintTracking:: Configuration {
20
- RemoteUserInputToArgumentToExecFlowConfig ( ) {
21
- this = "ExecCommon::RemoteUserInputToArgumentToExecFlowConfig"
22
- }
23
-
24
- override predicate isSource ( DataFlow:: Node src ) { src instanceof RemoteFlowSource }
27
+ class CommandInjectionAdditionalTaintStep extends Unit {
28
+ /**
29
+ * Holds if the step from `node1` to `node2` should be considered a taint
30
+ * step for configurations related to command injection.
31
+ */
32
+ abstract predicate step ( DataFlow:: Node node1 , DataFlow:: Node node2 ) ;
33
+ }
25
34
26
- override predicate isSink ( DataFlow:: Node sink ) { sink .asExpr ( ) instanceof ArgumentToExec }
35
+ private class DefaultCommandInjectionSink extends CommandInjectionSink {
36
+ DefaultCommandInjectionSink ( ) {
37
+ this .asExpr ( ) instanceof ArgumentToExec or sinkNode ( this , "command-injection" )
38
+ }
39
+ }
27
40
28
- override predicate isSanitizer ( DataFlow:: Node node ) {
29
- node .getType ( ) instanceof PrimitiveType
41
+ private class DefaultCommandInjectionSanitizer extends CommandInjectionSanitizer {
42
+ DefaultCommandInjectionSanitizer ( ) {
43
+ this .getType ( ) instanceof PrimitiveType
30
44
or
31
- node .getType ( ) instanceof BoxedType
45
+ this .getType ( ) instanceof BoxedType
32
46
or
33
- isSafeCommandArgument ( node .asExpr ( ) )
47
+ isSafeCommandArgument ( this .asExpr ( ) )
34
48
}
35
49
}
36
50
@@ -40,14 +54,12 @@ deprecated class RemoteUserInputToArgumentToExecFlowConfig extends TaintTracking
40
54
module RemoteUserInputToArgumentToExecFlowConfig implements DataFlow:: ConfigSig {
41
55
predicate isSource ( DataFlow:: Node src ) { src instanceof RemoteFlowSource }
42
56
43
- predicate isSink ( DataFlow:: Node sink ) { sink . asExpr ( ) instanceof ArgumentToExec }
57
+ predicate isSink ( DataFlow:: Node sink ) { sink instanceof CommandInjectionSink }
44
58
45
- predicate isBarrier ( DataFlow:: Node node ) {
46
- node .getType ( ) instanceof PrimitiveType
47
- or
48
- node .getType ( ) instanceof BoxedType
49
- or
50
- isSafeCommandArgument ( node .asExpr ( ) )
59
+ predicate isBarrier ( DataFlow:: Node node ) { node instanceof CommandInjectionSanitizer }
60
+
61
+ predicate isAdditionalFlowStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
62
+ any ( CommandInjectionAdditionalTaintStep s ) .step ( n1 , n2 )
51
63
}
52
64
}
53
65
@@ -58,29 +70,69 @@ module RemoteUserInputToArgumentToExecFlow =
58
70
TaintTracking:: Global< RemoteUserInputToArgumentToExecFlowConfig > ;
59
71
60
72
/**
61
- * DEPRECATED: Use `execIsTainted` instead.
62
- *
63
- * Implementation of `ExecTainted.ql`. It is extracted to a QLL
64
- * so that it can be excluded from `ExecUnescaped.ql` to avoid
65
- * reporting overlapping results.
73
+ * A taint-tracking configuration for unvalidated local user input that is used to run an external process.
66
74
*/
67
- deprecated predicate execTainted (
68
- DataFlow:: PathNode source , DataFlow:: PathNode sink , ArgumentToExec execArg
69
- ) {
70
- exists ( RemoteUserInputToArgumentToExecFlowConfig conf |
71
- conf .hasFlowPath ( source , sink ) and sink .getNode ( ) = DataFlow:: exprNode ( execArg )
72
- )
75
+ module LocalUserInputToArgumentToExecFlowConfig implements DataFlow:: ConfigSig {
76
+ predicate isSource ( DataFlow:: Node src ) { src instanceof LocalUserInput }
77
+
78
+ predicate isSink ( DataFlow:: Node sink ) { sink instanceof CommandInjectionSink }
79
+
80
+ predicate isBarrier ( DataFlow:: Node node ) { node instanceof CommandInjectionSanitizer }
81
+
82
+ predicate isAdditionalFlowStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
83
+ any ( CommandInjectionAdditionalTaintStep s ) .step ( n1 , n2 )
84
+ }
73
85
}
74
86
87
+ /**
88
+ * Taint-tracking flow for unvalidated local user input that is used to run an external process.
89
+ */
90
+ module LocalUserInputToArgumentToExecFlow =
91
+ TaintTracking:: Global< LocalUserInputToArgumentToExecFlowConfig > ;
92
+
75
93
/**
76
94
* Implementation of `ExecTainted.ql`. It is extracted to a QLL
77
95
* so that it can be excluded from `ExecUnescaped.ql` to avoid
78
96
* reporting overlapping results.
79
97
*/
80
98
predicate execIsTainted (
81
99
RemoteUserInputToArgumentToExecFlow:: PathNode source ,
82
- RemoteUserInputToArgumentToExecFlow:: PathNode sink , ArgumentToExec execArg
100
+ RemoteUserInputToArgumentToExecFlow:: PathNode sink , Expr execArg
83
101
) {
84
102
RemoteUserInputToArgumentToExecFlow:: flowPath ( source , sink ) and
85
- sink .getNode ( ) = DataFlow:: exprNode ( execArg )
103
+ sink .getNode ( ) .asExpr ( ) = execArg
104
+ }
105
+
106
+ /**
107
+ * DEPRECATED: Use `execIsTainted` instead.
108
+ *
109
+ * Implementation of `ExecTainted.ql`. It is extracted to a QLL
110
+ * so that it can be excluded from `ExecUnescaped.ql` to avoid
111
+ * reporting overlapping results.
112
+ */
113
+ deprecated predicate execTainted ( DataFlow:: PathNode source , DataFlow:: PathNode sink , Expr execArg ) {
114
+ exists ( RemoteUserInputToArgumentToExecFlowConfig conf |
115
+ conf .hasFlowPath ( source , sink ) and sink .getNode ( ) .asExpr ( ) = execArg
116
+ )
117
+ }
118
+
119
+ /**
120
+ * DEPRECATED: Use `RemoteUserInputToArgumentToExecFlow` instead.
121
+ *
122
+ * A taint-tracking configuration for unvalidated user input that is used to run an external process.
123
+ */
124
+ deprecated class RemoteUserInputToArgumentToExecFlowConfig extends TaintTracking:: Configuration {
125
+ RemoteUserInputToArgumentToExecFlowConfig ( ) {
126
+ this = "ExecCommon::RemoteUserInputToArgumentToExecFlowConfig"
127
+ }
128
+
129
+ override predicate isSource ( DataFlow:: Node src ) { src instanceof RemoteFlowSource }
130
+
131
+ override predicate isSink ( DataFlow:: Node sink ) { sink instanceof CommandInjectionSink }
132
+
133
+ override predicate isSanitizer ( DataFlow:: Node node ) { node instanceof CommandInjectionSanitizer }
134
+
135
+ override predicate isAdditionalTaintStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
136
+ any ( CommandInjectionAdditionalTaintStep s ) .step ( n1 , n2 )
137
+ }
86
138
}
0 commit comments