-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathUnicodeBypassValidationQuery.qll
More file actions
81 lines (72 loc) · 3.1 KB
/
UnicodeBypassValidationQuery.qll
File metadata and controls
81 lines (72 loc) · 3.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
* Provides a taint-tracking configuration for detecting "Unicode transformation mishandling" vulnerabilities.
*/
private import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.ApiGraphs
import semmle.python.Concepts
import semmle.python.dataflow.new.internal.DataFlowPublic
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.internal.TaintTrackingPrivate
import semmle.python.dataflow.new.RemoteFlowSources
import UnicodeBypassValidationCustomizations::UnicodeBypassValidation
abstract private class ValidationState extends string {
bindingset[this]
ValidationState() { any() }
}
/** A state signifying that a logical validation has not been performed. */
class PreValidation extends ValidationState {
PreValidation() { this = "PreValidation" }
}
/** A state signifying that a logical validation has been performed. */
class PostValidation extends ValidationState {
PostValidation() { this = "PostValidation" }
}
/**
* A taint-tracking configuration for detecting "Unicode transformation mishandling" vulnerabilities.
*
* This configuration uses two flow states, `PreValidation` and `PostValidation`,
* to track the requirement that a logical validation has been performed before the Unicode Transformation.
*/
private module UnicodeBypassValidationConfig implements DataFlow::StateConfigSig {
class FlowState = ValidationState;
predicate isSource(DataFlow::Node source, FlowState state) {
source instanceof RemoteFlowSource and state instanceof PreValidation
}
predicate isAdditionalFlowStep(
DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, FlowState stateTo
) {
(
exists(Escaping escaping | nodeFrom = escaping.getAnInput() and nodeTo = escaping.getOutput())
or
exists(RegexExecution re | nodeFrom = re.getString() and nodeTo = re)
or
stringManipulation(nodeFrom, nodeTo) and
not nodeTo.(DataFlow::MethodCallNode).getMethodName() in ["encode", "decode"]
) and
stateFrom instanceof PreValidation and
stateTo instanceof PostValidation
}
/* A Unicode Tranformation (Unicode tranformation) is considered a sink when the algorithm used is either NFC or NFKC. */
predicate isSink(DataFlow::Node sink, FlowState state) {
exists(API::CallNode cn |
cn = API::moduleImport("unicodedata").getMember("normalize").getACall() and
sink = cn.getArg(1)
or
cn = API::moduleImport("unidecode").getMember("unidecode").getACall() and
sink = cn.getArg(0)
or
cn = API::moduleImport("pyunormalize").getMember(["NFC", "NFD", "NFKC", "NFKD"]).getACall() and
sink = cn.getArg(0)
or
cn = API::moduleImport("pyunormalize").getMember("normalize").getACall() and
sink = cn.getArg(1)
or
cn = API::moduleImport("textnorm").getMember("normalize_unicode").getACall() and
sink = cn.getArg(0)
) and
state instanceof PostValidation
}
}
/** Global taint-tracking for detecting "Unicode transformation mishandling" vulnerabilities. */
module UnicodeBypassValidationFlow = TaintTracking::GlobalWithState<UnicodeBypassValidationConfig>;