Formatted

This commit is contained in:
aegilops
2023-06-16 17:33:21 +01:00
parent 55eeb00309
commit 8c73fbeabe
4 changed files with 129 additions and 135 deletions

View File

@@ -4,124 +4,103 @@ import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
// a static string of an unsafe executable tainting arg 0 of Runtime.exec()
class ExecTaintConfiguration extends TaintTracking::Configuration {
ExecTaintConfiguration() { this = "ExecTaintConfiguration" }
ExecTaintConfiguration() { this = "ExecTaintConfiguration" }
override
predicate
isSource(DataFlow::Node source) {
source.asExpr() instanceof StringLiteral
and source.asExpr().(StringLiteral).getValue() instanceof UnSafeExecutable
}
override predicate isSource(DataFlow::Node source) {
source.asExpr() instanceof StringLiteral and
source.asExpr().(StringLiteral).getValue() instanceof UnSafeExecutable
}
override
predicate
isSink(DataFlow::Node sink) {
exists(RuntimeExecMethod method, MethodAccess call |
call.getMethod() = method
and sink.asExpr() = call.getArgument(0)
and sink.asExpr().getType() instanceof Array
)
}
override predicate isSink(DataFlow::Node sink) {
exists(RuntimeExecMethod method, MethodAccess call |
call.getMethod() = method and
sink.asExpr() = call.getArgument(0) and
sink.asExpr().getType() instanceof Array
)
}
override
predicate
isSanitizer(DataFlow::Node node) {
node.asExpr().getFile().isSourceFile() and
(
node instanceof AssignToNonZeroIndex
or node instanceof ArrayInitAtNonZeroIndex
or node instanceof StreamConcatAtNonZeroIndex
or node.getType() instanceof PrimitiveType
or node.getType() instanceof BoxedType
)
}
override predicate isSanitizer(DataFlow::Node node) {
node.asExpr().getFile().isSourceFile() and
(
node instanceof AssignToNonZeroIndex or
node instanceof ArrayInitAtNonZeroIndex or
node instanceof StreamConcatAtNonZeroIndex or
node.getType() instanceof PrimitiveType or
node.getType() instanceof BoxedType
)
}
}
abstract class Source extends DataFlow::Node {
Source() {
this = this
}
Source() { this = this }
}
// taint flow from user data to args of the command
class ExecTaintConfiguration2 extends TaintTracking::Configuration {
ExecTaintConfiguration2() { this = "ExecTaintConfiguration2" }
ExecTaintConfiguration2() { this = "ExecTaintConfiguration2" }
override
predicate
isSource(DataFlow::Node source) {
source instanceof Source
}
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override
predicate
isSink(DataFlow::Node sink) {
exists(RuntimeExecMethod method, MethodAccess call, int index |
call.getMethod() = method
and sink.asExpr() = call.getArgument(index)
and sink.asExpr().getType() instanceof Array
)
}
override predicate isSink(DataFlow::Node sink) {
exists(RuntimeExecMethod method, MethodAccess call, int index |
call.getMethod() = method and
sink.asExpr() = call.getArgument(index) and
sink.asExpr().getType() instanceof Array
)
}
override
predicate
isSanitizer(DataFlow::Node node) {
node.asExpr().getFile().isSourceFile() and
(
node.getType() instanceof PrimitiveType
or node.getType() instanceof BoxedType
)
}
override predicate isSanitizer(DataFlow::Node node) {
node.asExpr().getFile().isSourceFile() and
(
node.getType() instanceof PrimitiveType or
node.getType() instanceof BoxedType
)
}
}
// array[3] = node
class AssignToNonZeroIndex extends DataFlow::Node {
AssignExpr assign;
ArrayAccess access;
AssignExpr assign;
ArrayAccess access;
AssignToNonZeroIndex() {
assign.getDest() = access
and access.getIndexExpr().(IntegerLiteral).getValue() != "0"
and assign.getSource() = this.asExpr()
}
AssignToNonZeroIndex() {
assign.getDest() = access and
access.getIndexExpr().(IntegerLiteral).getValue() != "0" and
assign.getSource() = this.asExpr()
}
}
// String[] array = {"a", "b, "c"};
class ArrayInitAtNonZeroIndex extends DataFlow::Node {
ArrayInit init;
int index;
ArrayInit init;
int index;
ArrayInitAtNonZeroIndex() {
init.getInit(index) = this.asExpr()
and index != 0
}
ArrayInitAtNonZeroIndex() {
init.getInit(index) = this.asExpr() and
index != 0
}
}
// Stream.concat(Arrays.stream(array_1), Arrays.stream(array_2))
class StreamConcatAtNonZeroIndex extends DataFlow::Node {
MethodAccess call;
int index;
MethodAccess call;
int index;
StreamConcatAtNonZeroIndex() {
call.getMethod().getQualifiedName() = "java.util.stream.Stream.concat"
and call.getArgument(index) = this.asExpr()
and index != 0
}
StreamConcatAtNonZeroIndex() {
call.getMethod().getQualifiedName() = "java.util.stream.Stream.concat" and
call.getArgument(index) = this.asExpr() and
index != 0
}
}
// allow list of executables that execute their arguments
// TODO: extend with data extensions
class UnSafeExecutable extends string {
bindingset[this]
UnSafeExecutable() {
this.regexpMatch("^(|.*/)([a-z]*sh|javac?|python.*|perl|[Pp]ower[Ss]hell|php|node|deno|bun|ruby|osascript|cmd|Rscript|groovy)(\\.exe)?$")
and not this.matches("netsh.exe")
}
bindingset[this]
UnSafeExecutable() {
this.regexpMatch("^(|.*/)([a-z]*sh|javac?|python.*|perl|[Pp]ower[Ss]hell|php|node|deno|bun|ruby|osascript|cmd|Rscript|groovy)(\\.exe)?$") and
not this.matches("netsh.exe")
}
}

View File

@@ -12,24 +12,29 @@
* external/cwe/cwe-078
*/
import DataFlow::PathGraph
import CommandInjectionRuntimeExec
class LocalSource extends Source { LocalSource() { this instanceof LocalUserInput } }
class LocalSource extends Source {
LocalSource() { this instanceof LocalUserInput }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, ExecTaintConfiguration2 conf, MethodAccess call, DataFlow::Node sourceCmd, DataFlow::Node sinkCmd, ExecTaintConfiguration confCmd
where call.getMethod() instanceof RuntimeExecMethod
// this is a command-accepting call to exec, e.g. rt.exec(new String[]{"/bin/sh", ...})
and (
confCmd.hasFlow(sourceCmd, sinkCmd)
and sinkCmd.asExpr() = call.getArgument(0)
)
// it is tainted by untrusted user input
and (
conf.hasFlow(source.getNode(), sink.getNode())
and sink.getNode().asExpr() = call.getArgument(0)
)
select sink, source, sink, "Call to dangerous java.lang.Runtime.exec() with command '$@' with arg from untrusted input '$@'",
sourceCmd, sourceCmd.toString(),
source.getNode(), source.toString()
from
DataFlow::PathNode source, DataFlow::PathNode sink, ExecTaintConfiguration2 conf,
MethodAccess call, DataFlow::Node sourceCmd, DataFlow::Node sinkCmd,
ExecTaintConfiguration confCmd
where
call.getMethod() instanceof RuntimeExecMethod and
// this is a command-accepting call to exec, e.g. rt.exec(new String[]{"/bin/sh", ...})
(
confCmd.hasFlow(sourceCmd, sinkCmd) and
sinkCmd.asExpr() = call.getArgument(0)
) and
// it is tainted by untrusted user input
(
conf.hasFlow(source.getNode(), sink.getNode()) and
sink.getNode().asExpr() = call.getArgument(0)
)
select sink, source, sink,
"Call to dangerous java.lang.Runtime.exec() with command '$@' with arg from untrusted input '$@'",
sourceCmd, sourceCmd.toString(), source.getNode(), source.toString()

View File

@@ -13,23 +13,27 @@
* external/cwe/cwe-078
*/
import CommandInjectionRuntimeExec
class DataSource extends Source { DataSource() { this instanceof RemoteFlowSource or this instanceof LocalUserInput } }
class DataSource extends Source {
DataSource() { this instanceof RemoteFlowSource or this instanceof LocalUserInput }
}
from DataFlow::Node source, DataFlow::Node sink, ExecTaintConfiguration2 conf, MethodAccess call, int index, DataFlow::Node sourceCmd, DataFlow::Node sinkCmd, ExecTaintConfiguration confCmd
where call.getMethod() instanceof RuntimeExecMethod
// this is a command-accepting call to exec, e.g. exec("/bin/sh", ...)
and (
confCmd.hasFlow(sourceCmd, sinkCmd)
and sinkCmd.asExpr() = call.getArgument(0)
)
// it is tainted by untrusted user input
and (
conf.hasFlow(source, sink)
and sink.asExpr() = call.getArgument(index)
)
select sink, "Call to dangerous java.lang.Runtime.exec() with command '$@' with arg from untrusted input '$@'",
sourceCmd, sourceCmd.toString(),
source, source.toString()
from
DataFlow::Node source, DataFlow::Node sink, ExecTaintConfiguration2 conf, MethodAccess call,
int index, DataFlow::Node sourceCmd, DataFlow::Node sinkCmd, ExecTaintConfiguration confCmd
where
call.getMethod() instanceof RuntimeExecMethod and
// this is a command-accepting call to exec, e.g. exec("/bin/sh", ...)
(
confCmd.hasFlow(sourceCmd, sinkCmd) and
sinkCmd.asExpr() = call.getArgument(0)
) and
// it is tainted by untrusted user input
(
conf.hasFlow(source, sink) and
sink.asExpr() = call.getArgument(index)
)
select sink,
"Call to dangerous java.lang.Runtime.exec() with command '$@' with arg from untrusted input '$@'",
sourceCmd, sourceCmd.toString(), source, source.toString()

View File

@@ -16,20 +16,26 @@
import DataFlow::PathGraph
import CommandInjectionRuntimeExec
class DataSource extends Source { DataSource() { this instanceof RemoteFlowSource or this instanceof LocalUserInput } }
class DataSource extends Source {
DataSource() { this instanceof RemoteFlowSource or this instanceof LocalUserInput }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, ExecTaintConfiguration2 conf, MethodAccess call, DataFlow::Node sourceCmd, DataFlow::Node sinkCmd, ExecTaintConfiguration confCmd
where call.getMethod() instanceof RuntimeExecMethod
// this is a command-accepting call to exec, e.g. rt.exec(new String[]{"/bin/sh", ...})
and (
confCmd.hasFlow(sourceCmd, sinkCmd)
and sinkCmd.asExpr() = call.getArgument(0)
)
// it is tainted by untrusted user input
and (
conf.hasFlow(source.getNode(), sink.getNode())
and sink.getNode().asExpr() = call.getArgument(0)
)
select sink, source, sink, "Call to dangerous java.lang.Runtime.exec() with command '$@' with arg from untrusted input '$@'",
sourceCmd, sourceCmd.toString(),
source.getNode(), source.toString()
from
DataFlow::PathNode source, DataFlow::PathNode sink, ExecTaintConfiguration2 conf,
MethodAccess call, DataFlow::Node sourceCmd, DataFlow::Node sinkCmd,
ExecTaintConfiguration confCmd
where
call.getMethod() instanceof RuntimeExecMethod and
// this is a command-accepting call to exec, e.g. rt.exec(new String[]{"/bin/sh", ...})
(
confCmd.hasFlow(sourceCmd, sinkCmd) and
sinkCmd.asExpr() = call.getArgument(0)
) and
// it is tainted by untrusted user input
(
conf.hasFlow(source.getNode(), sink.getNode()) and
sink.getNode().asExpr() = call.getArgument(0)
)
select sink, source, sink,
"Call to dangerous java.lang.Runtime.exec() with command '$@' with arg from untrusted input '$@'",
sourceCmd, sourceCmd.toString(), source.getNode(), source.toString()