mirror of
https://github.com/github/codeql.git
synced 2026-03-21 06:57:09 +01:00
136 lines
4.9 KiB
Plaintext
136 lines
4.9 KiB
Plaintext
/**
|
|
* Provides classes and methods common to queries `java/command-line-injection`, `java/command-line-concatenation`
|
|
* and their experimental derivatives.
|
|
*
|
|
* Do not import this from a library file, in order to reduce the risk of
|
|
* unintentionally bringing a TaintTracking::Configuration into scope in an unrelated
|
|
* query.
|
|
*/
|
|
|
|
import java
|
|
private import semmle.code.java.dataflow.FlowSources
|
|
private import semmle.code.java.dataflow.ExternalFlow
|
|
private import semmle.code.java.security.CommandArguments
|
|
private import semmle.code.java.security.ExternalProcess
|
|
private import semmle.code.java.security.Sanitizers
|
|
|
|
/** A sink for command injection vulnerabilities. */
|
|
abstract class CommandInjectionSink extends DataFlow::Node { }
|
|
|
|
/** A sanitizer for command injection vulnerabilities. */
|
|
abstract class CommandInjectionSanitizer extends DataFlow::Node { }
|
|
|
|
/**
|
|
* A unit class for adding additional taint steps.
|
|
*
|
|
* Extend this class to add additional taint steps that should apply to configurations related to command injection.
|
|
*/
|
|
class CommandInjectionAdditionalTaintStep extends Unit {
|
|
/**
|
|
* Holds if the step from `node1` to `node2` should be considered a taint
|
|
* step for configurations related to command injection.
|
|
*/
|
|
abstract predicate step(DataFlow::Node node1, DataFlow::Node node2);
|
|
}
|
|
|
|
private class DefaultCommandInjectionSink extends CommandInjectionSink {
|
|
DefaultCommandInjectionSink() { sinkNode(this, "command-injection") }
|
|
}
|
|
|
|
private class DefaultCommandInjectionSanitizer extends CommandInjectionSanitizer {
|
|
DefaultCommandInjectionSanitizer() {
|
|
this instanceof SimpleTypeSanitizer
|
|
or
|
|
isSafeCommandArgument(this.asExpr())
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A taint-tracking configuration for unvalidated user input that is used to run an external process.
|
|
*/
|
|
module RemoteUserInputToArgumentToExecFlowConfig implements DataFlow::ConfigSig {
|
|
predicate isSource(DataFlow::Node src) { src instanceof ThreatModelFlowSource }
|
|
|
|
predicate isSink(DataFlow::Node sink) { sink instanceof CommandInjectionSink }
|
|
|
|
predicate isBarrier(DataFlow::Node node) { node instanceof CommandInjectionSanitizer }
|
|
|
|
predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
|
|
any(CommandInjectionAdditionalTaintStep s).step(n1, n2)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Taint-tracking flow for unvalidated user input that is used to run an external process.
|
|
*/
|
|
module RemoteUserInputToArgumentToExecFlow =
|
|
TaintTracking::Global<RemoteUserInputToArgumentToExecFlowConfig>;
|
|
|
|
/**
|
|
* A taint-tracking configuration for unvalidated local user input that is used to run an external process.
|
|
*/
|
|
module LocalUserInputToArgumentToExecFlowConfig implements DataFlow::ConfigSig {
|
|
predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput }
|
|
|
|
predicate isSink(DataFlow::Node sink) { sink instanceof CommandInjectionSink }
|
|
|
|
predicate isBarrier(DataFlow::Node node) { node instanceof CommandInjectionSanitizer }
|
|
|
|
predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
|
|
any(CommandInjectionAdditionalTaintStep s).step(n1, n2)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Taint-tracking flow for unvalidated local user input that is used to run an external process.
|
|
*/
|
|
module LocalUserInputToArgumentToExecFlow =
|
|
TaintTracking::Global<LocalUserInputToArgumentToExecFlowConfig>;
|
|
|
|
/**
|
|
* Implementation of `ExecTainted.ql`. It is extracted to a QLL
|
|
* so that it can be excluded from `ExecUnescaped.ql` to avoid
|
|
* reporting overlapping results.
|
|
*/
|
|
predicate execIsTainted(
|
|
RemoteUserInputToArgumentToExecFlow::PathNode source,
|
|
RemoteUserInputToArgumentToExecFlow::PathNode sink, Expr execArg
|
|
) {
|
|
RemoteUserInputToArgumentToExecFlow::flowPath(source, sink) and
|
|
argumentToExec(execArg, sink.getNode())
|
|
}
|
|
|
|
/**
|
|
* DEPRECATED: Use `execIsTainted` instead.
|
|
*
|
|
* Implementation of `ExecTainted.ql`. It is extracted to a QLL
|
|
* so that it can be excluded from `ExecUnescaped.ql` to avoid
|
|
* reporting overlapping results.
|
|
*/
|
|
deprecated predicate execTainted(DataFlow::PathNode source, DataFlow::PathNode sink, Expr execArg) {
|
|
exists(RemoteUserInputToArgumentToExecFlowConfig conf |
|
|
conf.hasFlowPath(source, sink) and argumentToExec(execArg, sink.getNode())
|
|
)
|
|
}
|
|
|
|
/**
|
|
* DEPRECATED: Use `RemoteUserInputToArgumentToExecFlow` instead.
|
|
*
|
|
* A taint-tracking configuration for unvalidated user input that is used to run an external process.
|
|
*/
|
|
deprecated class RemoteUserInputToArgumentToExecFlowConfig extends TaintTracking::Configuration {
|
|
RemoteUserInputToArgumentToExecFlowConfig() {
|
|
this = "ExecCommon::RemoteUserInputToArgumentToExecFlowConfig"
|
|
}
|
|
|
|
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
|
|
|
|
override predicate isSink(DataFlow::Node sink) { sink instanceof CommandInjectionSink }
|
|
|
|
override predicate isSanitizer(DataFlow::Node node) { node instanceof CommandInjectionSanitizer }
|
|
|
|
override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
|
|
any(CommandInjectionAdditionalTaintStep s).step(n1, n2)
|
|
}
|
|
}
|