mirror of
https://github.com/github/codeql.git
synced 2026-04-24 08:15:14 +02:00
Convert all command injection sinks to MaD format
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `ExecCallable` class in `ExternalProcess.qll` has been deprecated.
|
||||
6
java/ql/lib/ext/experimental/com.jcraft.jsch.model.yml
Normal file
6
java/ql/lib/ext/experimental/com.jcraft.jsch.model.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: experimentalSinkModel
|
||||
data:
|
||||
- ["com.jcraft.jsch", "ChannelExec", True, "setCommand", "", "", "Argument[0]", "command-injection", "manual", "jsch-os-injection"]
|
||||
@@ -8,19 +8,20 @@ extensions:
|
||||
- ["java.lang", "ClassLoader", True, "getSystemResource", "(String)", "", "Argument[0]", "read-file", "ai-manual"]
|
||||
- ["java.lang", "ClassLoader", True, "getSystemResourceAsStream", "(String)", "", "Argument[0]", "read-file", "ai-manual"]
|
||||
- ["java.lang", "Module", True, "getResourceAsStream", "(String)", "", "Argument[0]", "read-file", "ai-manual"]
|
||||
# These are modeled in plain CodeQL. TODO: migrate them.
|
||||
# - ["java.lang", "ProcessBuilder", False, "command", "(String[])", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
# - ["java.lang", "ProcessBuilder", False, "directory", "(File)", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
# - ["java.lang", "ProcessBuilder", False, "ProcessBuilder", "(List)", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
# - ["java.lang", "ProcessBuilder", False, "ProcessBuilder", "(String[])", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
# - ["java.lang", "Runtime", True, "exec", "(String,String[])", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
# - ["java.lang", "Runtime", True, "exec", "(String[],String[])", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
# - ["java.lang", "Runtime", True, "exec", "(String,String[],File)", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
# - ["java.lang", "Runtime", True, "exec", "(String,String[],File)", "", "Argument[2]", "command-injection", "ai-manual"]
|
||||
# - ["java.lang", "Runtime", True, "exec", "(String)", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
# - ["java.lang", "Runtime", True, "exec", "(String[],String[],File)", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
# - ["java.lang", "Runtime", True, "exec", "(String[],String[],File)", "", "Argument[2]", "command-injection", "ai-manual"]
|
||||
# - ["java.lang", "Runtime", True, "exec", "(String[])", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "ProcessBuilder", False, "command", "(List)", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "ProcessBuilder", False, "command", "(String[])", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "ProcessBuilder", False, "command", "(String[])", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "ProcessBuilder", False, "directory", "(File)", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "ProcessBuilder", False, "ProcessBuilder", "(List)", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "ProcessBuilder", False, "ProcessBuilder", "(String[])", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "Runtime", True, "exec", "(String)", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "Runtime", True, "exec", "(String[])", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "Runtime", True, "exec", "(String[],String[])", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "Runtime", True, "exec", "(String[],String[],File)", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "Runtime", True, "exec", "(String[],String[],File)", "", "Argument[2]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "Runtime", True, "exec", "(String,String[])", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "Runtime", True, "exec", "(String,String[],File)", "", "Argument[0]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "Runtime", True, "exec", "(String,String[],File)", "", "Argument[2]", "command-injection", "ai-manual"]
|
||||
- ["java.lang", "String", False, "matches", "(String)", "", "Argument[0]", "regex-use[f-1]", "manual"]
|
||||
- ["java.lang", "String", False, "replaceAll", "(String,String)", "", "Argument[0]", "regex-use[-1]", "manual"]
|
||||
- ["java.lang", "String", False, "replaceFirst", "(String,String)", "", "Argument[0]", "regex-use[-1]", "manual"]
|
||||
|
||||
9
java/ql/lib/ext/org.apache.commons.exec.model.yml
Normal file
9
java/ql/lib/ext/org.apache.commons.exec.model.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["org.apache.commons.exec", "CommandLine", True, "parse", "(String)", "", "Argument[0]", "command-injection", "manual"]
|
||||
- ["org.apache.commons.exec", "CommandLine", True, "parse", "(String,Map)", "", "Argument[0]", "command-injection", "manual"]
|
||||
- ["org.apache.commons.exec", "CommandLine", True, "addArguments", "(String)", "", "Argument[0]", "command-injection", "manual"]
|
||||
- ["org.apache.commons.exec", "CommandLine", True, "addArguments", "(String,boolean)", "", "Argument[0]", "command-injection", "manual"]
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import Member
|
||||
import semmle.code.java.security.ExternalProcess
|
||||
private import semmle.code.java.dataflow.FlowSteps
|
||||
|
||||
// --- Standard types ---
|
||||
@@ -198,39 +197,6 @@ class TypeFile extends Class {
|
||||
}
|
||||
|
||||
// --- Standard methods ---
|
||||
/**
|
||||
* Any constructor of class `java.lang.ProcessBuilder`.
|
||||
*/
|
||||
class ProcessBuilderConstructor extends Constructor, ExecCallable {
|
||||
ProcessBuilderConstructor() { this.getDeclaringType() instanceof TypeProcessBuilder }
|
||||
|
||||
override int getAnExecutedArgument() { result = 0 }
|
||||
}
|
||||
|
||||
/**
|
||||
* Any of the methods named `command` on class `java.lang.ProcessBuilder`.
|
||||
*/
|
||||
class MethodProcessBuilderCommand extends Method, ExecCallable {
|
||||
MethodProcessBuilderCommand() {
|
||||
this.hasName("command") and
|
||||
this.getDeclaringType() instanceof TypeProcessBuilder
|
||||
}
|
||||
|
||||
override int getAnExecutedArgument() { result = 0 }
|
||||
}
|
||||
|
||||
/**
|
||||
* Any method named `exec` on class `java.lang.Runtime`.
|
||||
*/
|
||||
class MethodRuntimeExec extends Method, ExecCallable {
|
||||
MethodRuntimeExec() {
|
||||
this.hasName("exec") and
|
||||
this.getDeclaringType() instanceof TypeRuntime
|
||||
}
|
||||
|
||||
override int getAnExecutedArgument() { result = 0 }
|
||||
}
|
||||
|
||||
/**
|
||||
* Any method named `getenv` on class `java.lang.System`.
|
||||
*/
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/** Definitions related to the Apache Commons Exec library. */
|
||||
|
||||
import semmle.code.java.Type
|
||||
import semmle.code.java.security.ExternalProcess
|
||||
|
||||
/** The class `org.apache.commons.exec.CommandLine`. */
|
||||
private class TypeCommandLine extends Class {
|
||||
TypeCommandLine() { this.hasQualifiedName("org.apache.commons.exec", "CommandLine") }
|
||||
}
|
||||
|
||||
/** The `parse()` method of the class `org.apache.commons.exec.CommandLine`. */
|
||||
private class MethodCommandLineParse extends Method, ExecCallable {
|
||||
MethodCommandLineParse() {
|
||||
this.getDeclaringType() instanceof TypeCommandLine and
|
||||
this.hasName("parse")
|
||||
}
|
||||
|
||||
override int getAnExecutedArgument() { result = 0 }
|
||||
}
|
||||
|
||||
/** The `addArguments()` method of the class `org.apache.commons.exec.CommandLine`. */
|
||||
private class MethodCommandLineAddArguments extends Method, ExecCallable {
|
||||
MethodCommandLineAddArguments() {
|
||||
this.getDeclaringType() instanceof TypeCommandLine and
|
||||
this.hasName("addArguments")
|
||||
}
|
||||
|
||||
override int getAnExecutedArgument() { result = 0 }
|
||||
}
|
||||
@@ -10,8 +10,8 @@
|
||||
import java
|
||||
private import semmle.code.java.dataflow.FlowSources
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import semmle.code.java.security.ExternalProcess
|
||||
private import semmle.code.java.security.CommandArguments
|
||||
private import semmle.code.java.security.ExternalProcess
|
||||
|
||||
/** A sink for command injection vulnerabilities. */
|
||||
abstract class CommandInjectionSink extends DataFlow::Node { }
|
||||
@@ -33,9 +33,7 @@ class CommandInjectionAdditionalTaintStep extends Unit {
|
||||
}
|
||||
|
||||
private class DefaultCommandInjectionSink extends CommandInjectionSink {
|
||||
DefaultCommandInjectionSink() {
|
||||
this.asExpr() instanceof ArgumentToExec or sinkNode(this, "command-injection")
|
||||
}
|
||||
DefaultCommandInjectionSink() { sinkNode(this, "command-injection") }
|
||||
}
|
||||
|
||||
private class DefaultCommandInjectionSanitizer extends CommandInjectionSanitizer {
|
||||
@@ -100,7 +98,7 @@ predicate execIsTainted(
|
||||
RemoteUserInputToArgumentToExecFlow::PathNode sink, Expr execArg
|
||||
) {
|
||||
RemoteUserInputToArgumentToExecFlow::flowPath(source, sink) and
|
||||
sink.getNode().asExpr() = execArg
|
||||
argumentToExec(execArg, sink.getNode())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,7 +110,7 @@ predicate execIsTainted(
|
||||
*/
|
||||
deprecated predicate execTainted(DataFlow::PathNode source, DataFlow::PathNode sink, Expr execArg) {
|
||||
exists(RemoteUserInputToArgumentToExecFlowConfig conf |
|
||||
conf.hasFlowPath(source, sink) and sink.getNode().asExpr() = execArg
|
||||
conf.hasFlowPath(source, sink) and argumentToExec(execArg, sink.getNode())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
/** Definitions related to external processes. */
|
||||
|
||||
import semmle.code.java.Member
|
||||
|
||||
private module Instances {
|
||||
private import semmle.code.java.JDK
|
||||
private import semmle.code.java.frameworks.apache.Exec
|
||||
}
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
private import semmle.code.java.security.CommandLineQuery
|
||||
|
||||
/**
|
||||
* A callable that executes a command.
|
||||
* DEPRECATED: A callable that executes a command.
|
||||
*/
|
||||
abstract class ExecCallable extends Callable {
|
||||
abstract deprecated class ExecCallable extends Callable {
|
||||
/**
|
||||
* Gets the index of an argument that will be part of the command that is executed.
|
||||
*/
|
||||
@@ -23,13 +20,19 @@ abstract class ExecCallable extends Callable {
|
||||
* to be executed.
|
||||
*/
|
||||
class ArgumentToExec extends Expr {
|
||||
ArgumentToExec() {
|
||||
exists(Call execCall, ExecCallable execCallable, int i |
|
||||
execCall.getArgument(pragma[only_bind_into](i)) = this and
|
||||
execCallable = execCall.getCallee() and
|
||||
i = execCallable.getAnExecutedArgument()
|
||||
)
|
||||
}
|
||||
ArgumentToExec() { argumentToExec(this, _) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is an expression used as an argument to a call that executes an external command.
|
||||
* For calls to varargs method calls, this only includes the first argument, which will be the command
|
||||
* to be executed.
|
||||
*/
|
||||
predicate argumentToExec(Expr e, CommandInjectionSink s) {
|
||||
s.asExpr() = e
|
||||
or
|
||||
e.(Argument).isNthVararg(0) and
|
||||
s.(DataFlow::ImplicitVarargsArray).getCall() = e.(Argument).getCall()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,11 +14,14 @@
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.CommandLineQuery
|
||||
import semmle.code.java.security.ExternalProcess
|
||||
import LocalUserInputToArgumentToExecFlow::PathGraph
|
||||
|
||||
from
|
||||
LocalUserInputToArgumentToExecFlow::PathNode source,
|
||||
LocalUserInputToArgumentToExecFlow::PathNode sink
|
||||
where LocalUserInputToArgumentToExecFlow::flowPath(source, sink)
|
||||
select sink.getNode().asExpr(), source, sink, "This command line depends on a $@.",
|
||||
source.getNode(), "user-provided value"
|
||||
LocalUserInputToArgumentToExecFlow::PathNode sink, Expr e
|
||||
where
|
||||
LocalUserInputToArgumentToExecFlow::flowPath(source, sink) and
|
||||
argumentToExec(e, sink.getNode())
|
||||
select e, source, sink, "This command line depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.CommandLineQuery
|
||||
import semmle.code.java.security.ExternalProcess
|
||||
|
||||
/**
|
||||
* Strings that are known to be sane by some simple local analysis. Such strings
|
||||
|
||||
@@ -15,7 +15,11 @@
|
||||
import java
|
||||
import semmle.code.java.security.CommandLineQuery
|
||||
import RemoteUserInputToArgumentToExecFlow::PathGraph
|
||||
import JSchOSInjection
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
private class ActivateModels extends ActiveExperimentalModels {
|
||||
ActivateModels() { this = "jsch-os-injection" }
|
||||
}
|
||||
|
||||
// This is a clone of query `java/command-line-injection` that also includes experimental sinks.
|
||||
from
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* Provides classes for JSch OS command injection detection
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
/** The class `com.jcraft.jsch.ChannelExec`. */
|
||||
private class JSchChannelExec extends RefType {
|
||||
JSchChannelExec() { this.hasQualifiedName("com.jcraft.jsch", "ChannelExec") }
|
||||
}
|
||||
|
||||
/** A method to set an OS Command for the execution. */
|
||||
private class ChannelExecSetCommandMethod extends Method, ExecCallable {
|
||||
ChannelExecSetCommandMethod() {
|
||||
this.hasName("setCommand") and
|
||||
this.getDeclaringType() instanceof JSchChannelExec
|
||||
}
|
||||
|
||||
override int getAnExecutedArgument() { result = 0 }
|
||||
}
|
||||
@@ -1,22 +1,28 @@
|
||||
edges
|
||||
| Test.java:6:35:6:44 | arg : String | Test.java:7:44:7:69 | ... + ... |
|
||||
| Test.java:6:35:6:44 | arg : String | Test.java:7:44:7:69 | ... + ... : String |
|
||||
| Test.java:6:35:6:44 | arg : String | Test.java:10:61:10:73 | ... + ... : String |
|
||||
| Test.java:6:35:6:44 | arg : String | Test.java:16:13:16:25 | ... + ... : String |
|
||||
| Test.java:6:35:6:44 | arg : String | Test.java:22:15:22:27 | ... + ... : String |
|
||||
| Test.java:7:25:7:70 | new ..[] { .. } : String[] [[]] : String | Test.java:7:25:7:70 | new ..[] { .. } |
|
||||
| Test.java:7:44:7:69 | ... + ... : String | Test.java:7:25:7:70 | new ..[] { .. } : String[] [[]] : String |
|
||||
| Test.java:10:29:10:74 | {...} : String[] [[]] : String | Test.java:10:29:10:74 | new String[] |
|
||||
| Test.java:10:61:10:73 | ... + ... : String | Test.java:10:29:10:74 | {...} : String[] [[]] : String |
|
||||
| Test.java:16:5:16:7 | cmd [post update] : List [<element>] : String | Test.java:18:29:18:31 | cmd |
|
||||
| Test.java:16:13:16:25 | ... + ... : String | Test.java:16:5:16:7 | cmd [post update] : List [<element>] : String |
|
||||
| Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String | Test.java:24:29:24:32 | cmd1 |
|
||||
| Test.java:22:15:22:27 | ... + ... : String | Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String |
|
||||
| Test.java:28:38:28:47 | arg : String | Test.java:29:44:29:64 | ... + ... |
|
||||
| Test.java:28:38:28:47 | arg : String | Test.java:29:44:29:64 | ... + ... : String |
|
||||
| Test.java:29:25:29:65 | new ..[] { .. } : String[] [[]] : String | Test.java:29:25:29:65 | new ..[] { .. } |
|
||||
| Test.java:29:44:29:64 | ... + ... : String | Test.java:29:25:29:65 | new ..[] { .. } : String[] [[]] : String |
|
||||
| Test.java:57:27:57:39 | args : String[] | Test.java:60:20:60:22 | arg : String |
|
||||
| Test.java:57:27:57:39 | args : String[] | Test.java:61:23:61:25 | arg : String |
|
||||
| Test.java:60:20:60:22 | arg : String | Test.java:6:35:6:44 | arg : String |
|
||||
| Test.java:61:23:61:25 | arg : String | Test.java:28:38:28:47 | arg : String |
|
||||
nodes
|
||||
| Test.java:6:35:6:44 | arg : String | semmle.label | arg : String |
|
||||
| Test.java:7:44:7:69 | ... + ... | semmle.label | ... + ... |
|
||||
| Test.java:7:25:7:70 | new ..[] { .. } | semmle.label | new ..[] { .. } |
|
||||
| Test.java:7:25:7:70 | new ..[] { .. } : String[] [[]] : String | semmle.label | new ..[] { .. } : String[] [[]] : String |
|
||||
| Test.java:7:44:7:69 | ... + ... : String | semmle.label | ... + ... : String |
|
||||
| Test.java:10:29:10:74 | new String[] | semmle.label | new String[] |
|
||||
| Test.java:10:29:10:74 | {...} : String[] [[]] : String | semmle.label | {...} : String[] [[]] : String |
|
||||
| Test.java:10:61:10:73 | ... + ... : String | semmle.label | ... + ... : String |
|
||||
@@ -27,14 +33,16 @@ nodes
|
||||
| Test.java:22:15:22:27 | ... + ... : String | semmle.label | ... + ... : String |
|
||||
| Test.java:24:29:24:32 | cmd1 | semmle.label | cmd1 |
|
||||
| Test.java:28:38:28:47 | arg : String | semmle.label | arg : String |
|
||||
| Test.java:29:44:29:64 | ... + ... | semmle.label | ... + ... |
|
||||
| Test.java:29:25:29:65 | new ..[] { .. } | semmle.label | new ..[] { .. } |
|
||||
| Test.java:29:25:29:65 | new ..[] { .. } : String[] [[]] : String | semmle.label | new ..[] { .. } : String[] [[]] : String |
|
||||
| Test.java:29:44:29:64 | ... + ... : String | semmle.label | ... + ... : String |
|
||||
| Test.java:57:27:57:39 | args : String[] | semmle.label | args : String[] |
|
||||
| Test.java:60:20:60:22 | arg : String | semmle.label | arg : String |
|
||||
| Test.java:61:23:61:25 | arg : String | semmle.label | arg : String |
|
||||
subpaths
|
||||
#select
|
||||
| Test.java:7:44:7:69 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:7:44:7:69 | ... + ... | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
|
||||
| Test.java:7:44:7:69 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:7:25:7:70 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
|
||||
| Test.java:10:29:10:74 | new String[] | Test.java:57:27:57:39 | args : String[] | Test.java:10:29:10:74 | new String[] | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
|
||||
| Test.java:18:29:18:31 | cmd | Test.java:57:27:57:39 | args : String[] | Test.java:18:29:18:31 | cmd | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
|
||||
| Test.java:24:29:24:32 | cmd1 | Test.java:57:27:57:39 | args : String[] | Test.java:24:29:24:32 | cmd1 | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
|
||||
| Test.java:29:44:29:64 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:29:44:29:64 | ... + ... | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
|
||||
| Test.java:29:44:29:64 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:29:25:29:65 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
|
||||
|
||||
Reference in New Issue
Block a user