11import java
22import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
33import semmle.code.java.dataflow.DataFlow
4- private import semmle.code.java.dataflow.TaintTracking
54import semmle.code.java.dataflow.FlowSources
65
76// a static string of an unsafe executable tainting arg 0 of Runtime.exec()
8- class ExecTaintConfiguration extends TaintTracking:: Configuration {
7+ deprecated class ExecTaintConfiguration extends TaintTracking:: Configuration {
98 ExecTaintConfiguration ( ) { this = "ExecTaintConfiguration" }
109
1110 override predicate isSource ( DataFlow:: Node source ) {
@@ -33,12 +32,41 @@ class ExecTaintConfiguration extends TaintTracking::Configuration {
3332 }
3433}
3534
35+ module ExecCmdFlowConfig implements DataFlow:: ConfigSig {
36+ predicate isSource ( DataFlow:: Node source ) {
37+ source .asExpr ( ) instanceof StringLiteral and
38+ source .asExpr ( ) .( StringLiteral ) .getValue ( ) instanceof UnSafeExecutable
39+ }
40+
41+ predicate isSink ( DataFlow:: Node sink ) {
42+ exists ( RuntimeExecMethod method , MethodAccess call |
43+ call .getMethod ( ) = method and
44+ sink .asExpr ( ) = call .getArgument ( 0 ) and
45+ sink .asExpr ( ) .getType ( ) instanceof Array
46+ )
47+ }
48+
49+ predicate isBarrier ( DataFlow:: Node node ) {
50+ node .asExpr ( ) .getFile ( ) .isSourceFile ( ) and
51+ (
52+ node instanceof AssignToNonZeroIndex or
53+ node instanceof ArrayInitAtNonZeroIndex or
54+ node instanceof StreamConcatAtNonZeroIndex or
55+ node .getType ( ) instanceof PrimitiveType or
56+ node .getType ( ) instanceof BoxedType
57+ )
58+ }
59+ }
60+
61+ /** Tracks flow of unvalidated user input that is used in Runtime.Exec */
62+ module ExecCmdFlow = TaintTracking:: Global< ExecCmdFlowConfig > ;
63+
3664abstract class Source extends DataFlow:: Node {
3765 Source ( ) { this = this }
3866}
3967
4068// taint flow from user data to args of the command
41- class ExecTaintConfiguration2 extends TaintTracking:: Configuration {
69+ deprecated class ExecTaintConfiguration2 extends TaintTracking:: Configuration {
4270 ExecTaintConfiguration2 ( ) { this = "ExecTaintConfiguration2" }
4371
4472 override predicate isSource ( DataFlow:: Node source ) { source instanceof Source }
@@ -60,6 +88,31 @@ class ExecTaintConfiguration2 extends TaintTracking::Configuration {
6088 }
6189}
6290
91+ module ExecUserFlowConfig implements DataFlow:: ConfigSig {
92+ predicate isSource ( DataFlow:: Node source ) {
93+ source instanceof Source
94+ }
95+
96+ predicate isSink ( DataFlow:: Node sink ) {
97+ exists ( RuntimeExecMethod method , MethodAccess call |
98+ call .getMethod ( ) = method and
99+ sink .asExpr ( ) = call .getArgument ( _) and
100+ sink .asExpr ( ) .getType ( ) instanceof Array
101+ )
102+ }
103+
104+ predicate isBarrier ( DataFlow:: Node node ) {
105+ node .asExpr ( ) .getFile ( ) .isSourceFile ( ) and
106+ (
107+ node .getType ( ) instanceof PrimitiveType or
108+ node .getType ( ) instanceof BoxedType
109+ )
110+ }
111+ }
112+
113+ /** Tracks flow of unvalidated user input that is used in Runtime.Exec */
114+ module ExecUserFlow = TaintTracking:: Global< ExecUserFlowConfig > ;
115+
63116// array[3] = node
64117class AssignToNonZeroIndex extends DataFlow:: Node {
65118 AssignToNonZeroIndex ( ) {
@@ -101,3 +154,17 @@ class UnSafeExecutable extends string {
101154 not this = "netsh.exe"
102155 }
103156}
157+
158+ predicate callIsTaintedByUserInputAndDangerousCommand ( MethodAccess call , ExecUserFlow:: PathNode source , ExecUserFlow:: PathNode sink , DataFlow:: Node sourceCmd , DataFlow:: Node sinkCmd ) {
159+ call .getMethod ( ) instanceof RuntimeExecMethod and
160+ // this is a command-accepting call to exec, e.g. rt.exec(new String[]{"/bin/sh", ...})
161+ (
162+ ExecCmdFlow:: flow ( sourceCmd , sinkCmd ) and
163+ sinkCmd .asExpr ( ) = call .getArgument ( 0 )
164+ ) and
165+ // it is tainted by untrusted user input
166+ (
167+ ExecUserFlow:: flowPath ( source , sink ) and
168+ sink .getNode ( ) .asExpr ( ) = call .getArgument ( 0 )
169+ )
170+ }
0 commit comments