Skip to content

Commit fc7f840

Browse files
committed
Fix up for code review
1 parent 3658710 commit fc7f840

File tree

3 files changed

+30
-93
lines changed

3 files changed

+30
-93
lines changed

java/ql/src/experimental/Security/CWE/CWE-078/CommandInjectionRuntimeExec.ql

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@
1414
import CommandInjectionRuntimeExec
1515
import ExecUserFlow::PathGraph
1616

17-
class RemoteSource extends Source instanceof RemoteFlowSource { }
18-
1917
from
20-
ExecUserFlow::PathNode source, ExecUserFlow::PathNode sink, MethodAccess call,
21-
DataFlow::Node sourceCmd, DataFlow::Node sinkCmd
22-
where callIsTaintedByUserInputAndDangerousCommand(call, source, sink, sourceCmd, sinkCmd)
18+
ExecUserFlow::PathNode source, ExecUserFlow::PathNode sink, DataFlow::Node sourceCmd,
19+
DataFlow::Node sinkCmd
20+
where callIsTaintedByUserInputAndDangerousCommand(source, sink, sourceCmd, sinkCmd)
2321
select sink, source, sink,
2422
"Call to dangerous java.lang.Runtime.exec() with command '$@' with arg from untrusted input '$@'",
2523
sourceCmd, sourceCmd.toString(), source.getNode(), source.toString()

java/ql/src/experimental/Security/CWE/CWE-078/CommandInjectionRuntimeExec.qll

Lines changed: 24 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -3,108 +3,51 @@ import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
33
import semmle.code.java.dataflow.DataFlow
44
import semmle.code.java.dataflow.FlowSources
55

6-
// a static string of an unsafe executable tainting arg 0 of Runtime.exec()
7-
deprecated class ExecTaintConfiguration extends TaintTracking::Configuration {
8-
ExecTaintConfiguration() { this = "ExecTaintConfiguration" }
9-
10-
override predicate isSource(DataFlow::Node source) {
11-
source.asExpr() instanceof StringLiteral and
12-
source.asExpr().(StringLiteral).getValue() instanceof UnSafeExecutable
13-
}
14-
15-
override predicate isSink(DataFlow::Node sink) {
16-
exists(RuntimeExecMethod method, MethodAccess call |
17-
call.getMethod() = method and
18-
sink.asExpr() = call.getArgument(0) and
19-
sink.asExpr().getType() instanceof Array
20-
)
21-
}
22-
23-
override predicate isSanitizer(DataFlow::Node node) {
24-
node.asExpr().getFile().isSourceFile() and
25-
(
26-
node instanceof AssignToNonZeroIndex or
27-
node instanceof ArrayInitAtNonZeroIndex or
28-
node instanceof StreamConcatAtNonZeroIndex or
29-
node.getType() instanceof PrimitiveType or
30-
node.getType() instanceof BoxedType
31-
)
32-
}
33-
}
34-
356
module ExecCmdFlowConfig implements DataFlow::ConfigSig {
367
predicate isSource(DataFlow::Node source) {
37-
source.asExpr() instanceof StringLiteral and
38-
source.asExpr().(StringLiteral).getValue() instanceof UnSafeExecutable
8+
source.asExpr().(CompileTimeConstantExpr).getStringValue() instanceof UnSafeExecutable
399
}
4010

4111
predicate isSink(DataFlow::Node sink) {
42-
exists(RuntimeExecMethod method, MethodAccess call |
43-
call.getMethod() = method and
12+
exists(MethodAccess call |
13+
call.getMethod() instanceof RuntimeExecMethod and
4414
sink.asExpr() = call.getArgument(0) and
4515
sink.asExpr().getType() instanceof Array
4616
)
4717
}
4818

4919
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-
)
20+
node instanceof AssignToNonZeroIndex or
21+
node instanceof ArrayInitAtNonZeroIndex or
22+
node instanceof StreamConcatAtNonZeroIndex or
23+
node.getType() instanceof PrimitiveType or
24+
node.getType() instanceof BoxedType
5825
}
5926
}
6027

6128
/** Tracks flow of unvalidated user input that is used in Runtime.Exec */
6229
module ExecCmdFlow = TaintTracking::Global<ExecCmdFlowConfig>;
6330

64-
abstract class Source extends DataFlow::Node {
65-
Source() { this = this }
66-
}
67-
68-
// taint flow from user data to args of the command
69-
deprecated class ExecTaintConfiguration2 extends TaintTracking::Configuration {
70-
ExecTaintConfiguration2() { this = "ExecTaintConfiguration2" }
31+
abstract class Source extends DataFlow::Node { }
7132

72-
override predicate isSource(DataFlow::Node source) { source instanceof Source }
73-
74-
override predicate isSink(DataFlow::Node sink) {
75-
exists(RuntimeExecMethod method, MethodAccess call |
76-
call.getMethod() = method and
77-
sink.asExpr() = call.getArgument(_) and
78-
sink.asExpr().getType() instanceof Array
79-
)
80-
}
33+
class RemoteSource extends Source instanceof RemoteFlowSource { }
8134

82-
override predicate isSanitizer(DataFlow::Node node) {
83-
node.asExpr().getFile().isSourceFile() and
84-
(
85-
node.getType() instanceof PrimitiveType or
86-
node.getType() instanceof BoxedType
87-
)
88-
}
89-
}
35+
class LocalSource extends Source instanceof LocalUserInput { }
9036

9137
module ExecUserFlowConfig implements DataFlow::ConfigSig {
9238
predicate isSource(DataFlow::Node source) { source instanceof Source }
9339

9440
predicate isSink(DataFlow::Node sink) {
95-
exists(RuntimeExecMethod method, MethodAccess call |
96-
call.getMethod() = method and
41+
exists(MethodAccess call |
42+
call.getMethod() instanceof RuntimeExecMethod and
9743
sink.asExpr() = call.getArgument(_) and
9844
sink.asExpr().getType() instanceof Array
9945
)
10046
}
10147

10248
predicate isBarrier(DataFlow::Node node) {
103-
node.asExpr().getFile().isSourceFile() and
104-
(
105-
node.getType() instanceof PrimitiveType or
106-
node.getType() instanceof BoxedType
107-
)
49+
node.getType() instanceof PrimitiveType or
50+
node.getType() instanceof BoxedType
10851
}
10952
}
11053

@@ -116,7 +59,7 @@ class AssignToNonZeroIndex extends DataFlow::Node {
11659
AssignToNonZeroIndex() {
11760
exists(AssignExpr assign, ArrayAccess access |
11861
assign.getDest() = access and
119-
access.getIndexExpr().(IntegerLiteral).getValue() != "0" and
62+
access.getIndexExpr().(IntegerLiteral).getValue().toInt() != 0 and
12063
assign.getSource() = this.asExpr()
12164
)
12265
}
@@ -143,7 +86,7 @@ class StreamConcatAtNonZeroIndex extends DataFlow::Node {
14386
}
14487
}
14588

146-
// allow list of executables that execute their arguments
89+
// list of executables that execute their arguments
14790
// TODO: extend with data extensions
14891
class UnSafeExecutable extends string {
14992
bindingset[this]
@@ -154,17 +97,15 @@ class UnSafeExecutable extends string {
15497
}
15598

15699
predicate callIsTaintedByUserInputAndDangerousCommand(
157-
MethodAccess call, ExecUserFlow::PathNode source, ExecUserFlow::PathNode sink,
158-
DataFlow::Node sourceCmd, DataFlow::Node sinkCmd
100+
ExecUserFlow::PathNode source, ExecUserFlow::PathNode sink, DataFlow::Node sourceCmd,
101+
DataFlow::Node sinkCmd
159102
) {
160-
call.getMethod() instanceof RuntimeExecMethod and
161-
// this is a command-accepting call to exec, e.g. rt.exec(new String[]{"/bin/sh", ...})
162-
(
103+
exists(MethodAccess call |
104+
call.getMethod() instanceof RuntimeExecMethod and
105+
// this is a command-accepting call to exec, e.g. rt.exec(new String[]{"/bin/sh", ...})
163106
ExecCmdFlow::flow(sourceCmd, sinkCmd) and
164-
sinkCmd.asExpr() = call.getArgument(0)
165-
) and
166-
// it is tainted by untrusted user input
167-
(
107+
sinkCmd.asExpr() = call.getArgument(0) and
108+
// it is tainted by untrusted user input
168109
ExecUserFlow::flowPath(source, sink) and
169110
sink.getNode().asExpr() = call.getArgument(0)
170111
)

java/ql/src/experimental/Security/CWE/CWE-078/CommandInjectionRuntimeExecLocal.ql

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@
1515
import CommandInjectionRuntimeExec
1616
import ExecUserFlow::PathGraph
1717

18-
class LocalSource extends Source instanceof LocalUserInput { }
19-
2018
from
21-
ExecUserFlow::PathNode source, ExecUserFlow::PathNode sink, MethodAccess call,
22-
DataFlow::Node sourceCmd, DataFlow::Node sinkCmd
23-
where callIsTaintedByUserInputAndDangerousCommand(call, source, sink, sourceCmd, sinkCmd)
19+
ExecUserFlow::PathNode source, ExecUserFlow::PathNode sink, DataFlow::Node sourceCmd,
20+
DataFlow::Node sinkCmd
21+
where callIsTaintedByUserInputAndDangerousCommand(source, sink, sourceCmd, sinkCmd)
2422
select sink, source, sink,
2523
"Call to dangerous java.lang.Runtime.exec() with command '$@' with arg from untrusted input '$@'",
2624
sourceCmd, sourceCmd.toString(), source.getNode(), source.toString()

0 commit comments

Comments
 (0)