C++: Update UnsafeCreateProcessCall with DataFlow::ConfigSig

This commit is contained in:
Jeroen Ketema
2023-03-08 14:52:03 +01:00
parent af612a12de
commit 53aa34bdd3

View File

@@ -13,7 +13,6 @@
import cpp import cpp
import semmle.code.cpp.ir.dataflow.DataFlow import semmle.code.cpp.ir.dataflow.DataFlow
import semmle.code.cpp.ir.dataflow.DataFlow2
predicate isCreateProcessFunction(FunctionCall call, int applicationNameIndex, int commandLineIndex) { predicate isCreateProcessFunction(FunctionCall call, int applicationNameIndex, int commandLineIndex) {
call.getTarget().hasGlobalName("CreateProcessA") and 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 * Dataflow that detects a call to CreateProcess with a NULL value for lpApplicationName argument
*/ */
class NullAppNameCreateProcessFunctionConfiguration extends DataFlow::Configuration { module NullAppNameCreateProcessFunctionConfiguration implements DataFlow::ConfigSig {
NullAppNameCreateProcessFunctionConfiguration() { predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue }
this = "NullAppNameCreateProcessFunctionConfiguration"
}
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue } predicate isSink(DataFlow::Node sink) {
override predicate isSink(DataFlow::Node sink) {
exists(CreateProcessFunctionCall call, Expr val | val = sink.asExpr() | exists(CreateProcessFunctionCall call, Expr val | val = sink.asExpr() |
val = call.getArgument(call.getApplicationNameArgumentId()) val = call.getArgument(call.getApplicationNameArgumentId())
) )
} }
} }
module NullAppNameCreateProcessFunction =
DataFlow::Make<NullAppNameCreateProcessFunctionConfiguration>;
/** /**
* Dataflow that detects a call to CreateProcess with an unquoted commandLine argument * Dataflow that detects a call to CreateProcess with an unquoted commandLine argument
*/ */
class QuotedCommandInCreateProcessFunctionConfiguration extends DataFlow2::Configuration { module QuotedCommandInCreateProcessFunctionConfiguration implements DataFlow::ConfigSig {
QuotedCommandInCreateProcessFunctionConfiguration() { predicate isSource(DataFlow::Node source) {
this = "QuotedCommandInCreateProcessFunctionConfiguration"
}
override predicate isSource(DataFlow2::Node source) {
exists(string s | exists(string s |
s = source.asExpr().getValue().toString() and s = source.asExpr().getValue().toString() and
not isQuotedOrNoSpaceApplicationNameOnCmd(s) not isQuotedOrNoSpaceApplicationNameOnCmd(s)
) )
} }
override predicate isSink(DataFlow2::Node sink) { predicate isSink(DataFlow::Node sink) {
exists(CreateProcessFunctionCall call, Expr val | val = sink.asExpr() | exists(CreateProcessFunctionCall call, Expr val | val = sink.asExpr() |
val = call.getArgument(call.getCommandLineArgumentId()) val = call.getArgument(call.getCommandLineArgumentId())
) )
} }
} }
module QuotedCommandInCreateProcessFunction =
DataFlow::Make<QuotedCommandInCreateProcessFunctionConfiguration>;
bindingset[s] bindingset[s]
predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) { predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) {
s.regexpMatch("\"([^\"])*\"[\\s\\S]*") // The first element (path) is quoted 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 from CreateProcessFunctionCall call, string msg1, string msg2
where where
exists(Expr appName, NullAppNameCreateProcessFunctionConfiguration nullAppConfig | exists(Expr appName |
appName = call.getArgument(call.getApplicationNameArgumentId()) and appName = call.getArgument(call.getApplicationNameArgumentId()) and
nullAppConfig.hasFlowToExpr(appName) and NullAppNameCreateProcessFunction::hasFlowToExpr(appName) and
msg1 = call.toString() + " with lpApplicationName == NULL (" + appName + ")" msg1 = call.toString() + " with lpApplicationName == NULL (" + appName + ")"
) and ) and
exists(Expr cmd, QuotedCommandInCreateProcessFunctionConfiguration quotedConfig | exists(Expr cmd |
cmd = call.getArgument(call.getCommandLineArgumentId()) and cmd = call.getArgument(call.getCommandLineArgumentId()) and
quotedConfig.hasFlowToExpr(cmd) and QuotedCommandInCreateProcessFunction::hasFlowToExpr(cmd) and
msg2 = msg2 =
" and with an unquoted lpCommandLine (" + cmd + " and with an unquoted lpCommandLine (" + cmd +
") introduces a security vulnerability if the path contains spaces." ") introduces a security vulnerability if the path contains spaces."