77 * query.
88 */
99
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 { }
1321
1422/**
15- * DEPRECATED: Use `RemoteUserInputToArgumentToExecFlow` instead .
23+ * A unit class for adding additional taint steps .
1624 *
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 .
1826 */
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+ }
2534
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+ }
2740
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
3044 or
31- node .getType ( ) instanceof BoxedType
45+ this .getType ( ) instanceof BoxedType
3246 or
33- isSafeCommandArgument ( node .asExpr ( ) )
47+ isSafeCommandArgument ( this .asExpr ( ) )
3448 }
3549}
3650
@@ -40,14 +54,12 @@ deprecated class RemoteUserInputToArgumentToExecFlowConfig extends TaintTracking
4054module RemoteUserInputToArgumentToExecFlowConfig implements DataFlow:: ConfigSig {
4155 predicate isSource ( DataFlow:: Node src ) { src instanceof RemoteFlowSource }
4256
43- predicate isSink ( DataFlow:: Node sink ) { sink . asExpr ( ) instanceof ArgumentToExec }
57+ predicate isSink ( DataFlow:: Node sink ) { sink instanceof CommandInjectionSink }
4458
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 )
5163 }
5264}
5365
@@ -58,29 +70,69 @@ module RemoteUserInputToArgumentToExecFlow =
5870 TaintTracking:: Global< RemoteUserInputToArgumentToExecFlowConfig > ;
5971
6072/**
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.
6674 */
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+ }
7385}
7486
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+
7593/**
7694 * Implementation of `ExecTainted.ql`. It is extracted to a QLL
7795 * so that it can be excluded from `ExecUnescaped.ql` to avoid
7896 * reporting overlapping results.
7997 */
8098predicate execIsTainted (
8199 RemoteUserInputToArgumentToExecFlow:: PathNode source ,
82- RemoteUserInputToArgumentToExecFlow:: PathNode sink , ArgumentToExec execArg
100+ RemoteUserInputToArgumentToExecFlow:: PathNode sink , Expr execArg
83101) {
84102 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+ }
86138}
0 commit comments