mirror of
https://github.com/github/codeql.git
synced 2025-12-23 20:26:32 +01:00
C++: Update UnsafeCreateProcessCall with DataFlow::ConfigSig
This commit is contained in:
@@ -13,7 +13,6 @@
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow2
|
||||
|
||||
predicate isCreateProcessFunction(FunctionCall call, int applicationNameIndex, int commandLineIndex) {
|
||||
call.getTarget().hasGlobalName("CreateProcessA") and
|
||||
@@ -55,42 +54,40 @@ class CreateProcessFunctionCall extends FunctionCall {
|
||||
/**
|
||||
* Dataflow that detects a call to CreateProcess with a NULL value for lpApplicationName argument
|
||||
*/
|
||||
class NullAppNameCreateProcessFunctionConfiguration extends DataFlow::Configuration {
|
||||
NullAppNameCreateProcessFunctionConfiguration() {
|
||||
this = "NullAppNameCreateProcessFunctionConfiguration"
|
||||
}
|
||||
module NullAppNameCreateProcessFunctionConfiguration implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(CreateProcessFunctionCall call, Expr val | val = sink.asExpr() |
|
||||
val = call.getArgument(call.getApplicationNameArgumentId())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module NullAppNameCreateProcessFunction =
|
||||
DataFlow::Make<NullAppNameCreateProcessFunctionConfiguration>;
|
||||
|
||||
/**
|
||||
* Dataflow that detects a call to CreateProcess with an unquoted commandLine argument
|
||||
*/
|
||||
class QuotedCommandInCreateProcessFunctionConfiguration extends DataFlow2::Configuration {
|
||||
QuotedCommandInCreateProcessFunctionConfiguration() {
|
||||
this = "QuotedCommandInCreateProcessFunctionConfiguration"
|
||||
}
|
||||
|
||||
override predicate isSource(DataFlow2::Node source) {
|
||||
module QuotedCommandInCreateProcessFunctionConfiguration implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(string s |
|
||||
s = source.asExpr().getValue().toString() and
|
||||
not isQuotedOrNoSpaceApplicationNameOnCmd(s)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow2::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(CreateProcessFunctionCall call, Expr val | val = sink.asExpr() |
|
||||
val = call.getArgument(call.getCommandLineArgumentId())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module QuotedCommandInCreateProcessFunction =
|
||||
DataFlow::Make<QuotedCommandInCreateProcessFunctionConfiguration>;
|
||||
|
||||
bindingset[s]
|
||||
predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) {
|
||||
s.regexpMatch("\"([^\"])*\"[\\s\\S]*") // The first element (path) is quoted
|
||||
@@ -100,14 +97,14 @@ predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) {
|
||||
|
||||
from CreateProcessFunctionCall call, string msg1, string msg2
|
||||
where
|
||||
exists(Expr appName, NullAppNameCreateProcessFunctionConfiguration nullAppConfig |
|
||||
exists(Expr appName |
|
||||
appName = call.getArgument(call.getApplicationNameArgumentId()) and
|
||||
nullAppConfig.hasFlowToExpr(appName) and
|
||||
NullAppNameCreateProcessFunction::hasFlowToExpr(appName) and
|
||||
msg1 = call.toString() + " with lpApplicationName == NULL (" + appName + ")"
|
||||
) and
|
||||
exists(Expr cmd, QuotedCommandInCreateProcessFunctionConfiguration quotedConfig |
|
||||
exists(Expr cmd |
|
||||
cmd = call.getArgument(call.getCommandLineArgumentId()) and
|
||||
quotedConfig.hasFlowToExpr(cmd) and
|
||||
QuotedCommandInCreateProcessFunction::hasFlowToExpr(cmd) and
|
||||
msg2 =
|
||||
" and with an unquoted lpCommandLine (" + cmd +
|
||||
") introduces a security vulnerability if the path contains spaces."
|
||||
|
||||
Reference in New Issue
Block a user