C++: Update UnsafeDaclSecurityDescriptor with DataFlow::ConfigSig

This commit is contained in:
Jeroen Ketema
2023-03-08 14:55:03 +01:00
parent 7fe1a9431c
commit 8253f2d343

View File

@@ -15,7 +15,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
/** /**
* A function call to SetSecurityDescriptorDacl to set the ACL, specified by (2nd argument) bDaclPresent = TRUE * A function call to SetSecurityDescriptorDacl to set the ACL, specified by (2nd argument) bDaclPresent = TRUE
@@ -30,26 +29,24 @@ class SetSecurityDescriptorDaclFunctionCall extends FunctionCall {
/** /**
* Dataflow that detects a call to SetSecurityDescriptorDacl with a NULL DACL as the pDacl argument * Dataflow that detects a call to SetSecurityDescriptorDacl with a NULL DACL as the pDacl argument
*/ */
class NullDaclConfig extends DataFlow::Configuration { module NullDaclConfig implements DataFlow::ConfigSig {
NullDaclConfig() { this = "NullDaclConfig" } predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue }
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue } predicate isSink(DataFlow::Node sink) {
override predicate isSink(DataFlow::Node sink) {
exists(SetSecurityDescriptorDaclFunctionCall call, VariableAccess val | val = sink.asExpr() | exists(SetSecurityDescriptorDaclFunctionCall call, VariableAccess val | val = sink.asExpr() |
val = call.getArgument(2) val = call.getArgument(2)
) )
} }
} }
module NullDaclFlow = DataFlow::Make<NullDaclConfig>;
/** /**
* Dataflow that detects a call to SetSecurityDescriptorDacl with a pDacl * Dataflow that detects a call to SetSecurityDescriptorDacl with a pDacl
* argument that's _not_ likely to be NULL. * argument that's _not_ likely to be NULL.
*/ */
class NonNullDaclConfig extends DataFlow2::Configuration { module NonNullDaclConfig implements DataFlow::ConfigSig {
NonNullDaclConfig() { this = "NonNullDaclConfig" } predicate isSource(DataFlow::Node source) {
override predicate isSource(DataFlow::Node source) {
source.getType().getUnspecifiedType().(PointerType).getBaseType() = source.getType().getUnspecifiedType().(PointerType).getBaseType() =
any(Type t | t.getName() = "ACL").getUnspecifiedType() and any(Type t | t.getName() = "ACL").getUnspecifiedType() and
( (
@@ -68,11 +65,13 @@ class NonNullDaclConfig extends DataFlow2::Configuration {
) )
} }
override predicate isSink(DataFlow::Node sink) { predicate isSink(DataFlow::Node sink) {
exists(SetSecurityDescriptorDaclFunctionCall call | sink.asExpr() = call.getArgument(2)) exists(SetSecurityDescriptorDaclFunctionCall call | sink.asExpr() = call.getArgument(2))
} }
} }
module NonNullDaclFlow = DataFlow::Make<NonNullDaclConfig>;
from SetSecurityDescriptorDaclFunctionCall call, string message from SetSecurityDescriptorDaclFunctionCall call, string message
where where
exists(NullValue nullExpr | exists(NullValue nullExpr |
@@ -83,13 +82,13 @@ where
call.getArgument(2) = nullExpr call.getArgument(2) = nullExpr
) )
or or
exists(VariableAccess var, NullDaclConfig nullDaclConfig, NonNullDaclConfig nonNullDaclConfig | exists(VariableAccess var |
message = message =
"Setting a DACL to NULL in a SECURITY_DESCRIPTOR using variable " + var + "Setting a DACL to NULL in a SECURITY_DESCRIPTOR using variable " + var +
" that is set to NULL will result in an unprotected object." " that is set to NULL will result in an unprotected object."
| |
var = call.getArgument(2) and var = call.getArgument(2) and
nullDaclConfig.hasFlowToExpr(var) and NullDaclFlow::hasFlowToExpr(var) and
not nonNullDaclConfig.hasFlowToExpr(var) not NonNullDaclFlow::hasFlowToExpr(var)
) )
select call, message select call, message