diff --git a/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidation.ql b/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidation.ql index 67c61653763..f830c0ea25d 100644 --- a/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidation.ql +++ b/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidation.ql @@ -14,10 +14,10 @@ import python import UnicodeBypassValidationQuery -import DataFlow::PathGraph +import UnicodeBypassValidationFlow::PathGraph -from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink -where config.hasFlowPath(source, sink) +from UnicodeBypassValidationFlow::PathNode source, UnicodeBypassValidationFlow::PathNode sink +where UnicodeBypassValidationFlow::flowPath(source, sink) select sink.getNode(), source, sink, "This $@ processes unsafely $@ and any logical validation in-between could be bypassed using special Unicode characters.", sink.getNode(), "Unicode transformation (Unicode normalization)", source.getNode(), diff --git a/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidationQuery.qll b/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidationQuery.qll index 702a69a7095..169c71a0c09 100644 --- a/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidationQuery.qll +++ b/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidationQuery.qll @@ -3,6 +3,7 @@ */ private import python +import semmle.python.dataflow.new.DataFlow import semmle.python.ApiGraphs import semmle.python.Concepts import semmle.python.dataflow.new.internal.DataFlowPublic @@ -27,16 +28,16 @@ class PostValidation extends DataFlow::FlowState { * This configuration uses two flow states, `PreValidation` and `PostValidation`, * to track the requirement that a logical validation has been performed before the Unicode Transformation. */ -class Configuration extends TaintTracking::Configuration { - Configuration() { this = "UnicodeBypassValidation" } +private module UnicodeBypassValidationConfig implements DataFlow::StateConfigSig { + class FlowState = DataFlow::FlowState; - override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { + predicate isSource(DataFlow::Node source, FlowState state) { source instanceof RemoteFlowSource and state instanceof PreValidation } - override predicate isAdditionalTaintStep( - DataFlow::Node nodeFrom, DataFlow::FlowState stateFrom, DataFlow::Node nodeTo, - DataFlow::FlowState stateTo + predicate isAdditionalFlowStep( + DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, + FlowState stateTo ) { ( exists(Escaping escaping | nodeFrom = escaping.getAnInput() and nodeTo = escaping.getOutput()) @@ -51,7 +52,7 @@ class Configuration extends TaintTracking::Configuration { } /* A Unicode Tranformation (Unicode tranformation) is considered a sink when the algorithm used is either NFC or NFKC. */ - override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { + predicate isSink(DataFlow::Node sink, FlowState state) { exists(API::CallNode cn | cn = API::moduleImport("unicodedata").getMember("normalize").getACall() and sink = cn.getArg(1) @@ -71,3 +72,6 @@ class Configuration extends TaintTracking::Configuration { state instanceof PostValidation } } + +/** Global taint-tracking for detecting "Unicode transformation mishandling" vulnerabilities. */ +module UnicodeBypassValidationFlow = TaintTracking::GlobalWithState;