@@ -13,38 +13,92 @@ private import codeql.ruby.dataflow.BarrierGuards
13
13
module CodeInjection {
14
14
/** Flow states used to distinguish whether an attacker controls the entire string. */
15
15
module FlowState {
16
- /** Flow state used for normal tainted data, where an attacker might only control a substring. */
17
- DataFlow:: FlowState substring ( ) { result = "substring" }
16
+ /**
17
+ * Flow state used for normal tainted data, where an attacker might only control a substring.
18
+ * DEPRECATED: Use `Full()`
19
+ */
20
+ deprecated DataFlow:: FlowState substring ( ) { result = "substring" }
21
+
22
+ /**
23
+ * Flow state used for data that is entirely controlled by the attacker.
24
+ * DEPRECATED: Use `Full()`
25
+ */
26
+ deprecated DataFlow:: FlowState full ( ) { result = "full" }
27
+
28
+ private newtype TState =
29
+ TFull ( ) or
30
+ TSubString ( )
31
+
32
+ /** Flow states used to distinguish whether an attacker controls the entire string. */
33
+ class State extends TState {
34
+ string toString ( ) {
35
+ this = TSubString ( ) and result = "substring"
36
+ or
37
+ this = TFull ( ) and result = "full"
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Flow state used for normal tainted data, where an attacker might only control a substring.
43
+ */
44
+ class SubString extends State , TSubString { }
18
45
19
- /** Flow state used for data that is entirely controlled by the attacker. */
20
- DataFlow:: FlowState full ( ) { result = "full" }
46
+ /**
47
+ * Flow state used for data that is entirely controlled by the attacker.
48
+ */
49
+ class Full extends State , TFull { }
21
50
}
22
51
23
52
/**
24
53
* A data flow source for "Code injection" vulnerabilities.
25
54
*/
26
55
abstract class Source extends DataFlow:: Node {
56
+ /**
57
+ * Gets a flow state for which this is a source.
58
+ * DEPRECATED: Use `getAState()`
59
+ */
60
+ deprecated DataFlow:: FlowState getAFlowState ( ) {
61
+ result = [ FlowState:: substring ( ) , FlowState:: full ( ) ]
62
+ }
63
+
27
64
/** Gets a flow state for which this is a source. */
28
- DataFlow:: FlowState getAFlowState ( ) { result = [ FlowState:: substring ( ) , FlowState:: full ( ) ] }
65
+ FlowState:: State getAState ( ) {
66
+ result instanceof FlowState:: SubString or result instanceof FlowState:: Full
67
+ }
29
68
}
30
69
31
70
/**
32
71
* A data flow sink for "Code injection" vulnerabilities.
33
72
*/
34
73
abstract class Sink extends DataFlow:: Node {
74
+ /**
75
+ * Holds if this sink is safe for an attacker that only controls a substring.
76
+ * DEPRECATED: Use `getAState()`
77
+ */
78
+ deprecated DataFlow:: FlowState getAFlowState ( ) {
79
+ result = [ FlowState:: substring ( ) , FlowState:: full ( ) ]
80
+ }
81
+
35
82
/** Holds if this sink is safe for an attacker that only controls a substring. */
36
- DataFlow :: FlowState getAFlowState ( ) { result = [ FlowState :: substring ( ) , FlowState :: full ( ) ] }
83
+ FlowState :: State getAState ( ) { any ( ) }
37
84
}
38
85
39
86
/**
40
87
* A sanitizer for "Code injection" vulnerabilities.
41
88
*/
42
89
abstract class Sanitizer extends DataFlow:: Node {
90
+ /**
91
+ * Gets a flow state for which this is a sanitizer.
92
+ * Sanitizes all states if the result is empty.
93
+ * DEPRECATED: Use `getAState()`
94
+ */
95
+ deprecated DataFlow:: FlowState getAFlowState ( ) { none ( ) }
96
+
43
97
/**
44
98
* Gets a flow state for which this is a sanitizer.
45
99
* Sanitizes all states if the result is empty.
46
100
*/
47
- DataFlow :: FlowState getAFlowState ( ) { none ( ) }
101
+ FlowState :: State getAState ( ) { none ( ) }
48
102
}
49
103
50
104
/**
@@ -67,12 +121,17 @@ module CodeInjection {
67
121
68
122
CodeExecutionAsSink ( ) { this = c .getCode ( ) }
69
123
70
- /** Gets a flow state for which this is a sink. */
71
- override DataFlow:: FlowState getAFlowState ( ) {
124
+ deprecated override DataFlow:: FlowState getAFlowState ( ) {
72
125
if c .runsArbitraryCode ( )
73
126
then result = [ FlowState:: substring ( ) , FlowState:: full ( ) ] // If it runs arbitrary code then it's always vulnerable.
74
127
else result = FlowState:: full ( ) // If it "just" loads something, then it's only vulnerable if the attacker controls the entire string.
75
128
}
129
+
130
+ override FlowState:: State getAState ( ) {
131
+ if c .runsArbitraryCode ( )
132
+ then any ( ) // If it runs arbitrary code then it's always vulnerable.
133
+ else result instanceof FlowState:: Full // If it "just" loads something, then it's only vulnerable if the attacker controls the entire string.
134
+ }
76
135
}
77
136
78
137
private import codeql.ruby.AST as Ast
@@ -92,6 +151,8 @@ module CodeInjection {
92
151
)
93
152
}
94
153
95
- override DataFlow:: FlowState getAFlowState ( ) { result = FlowState:: full ( ) }
154
+ deprecated override DataFlow:: FlowState getAFlowState ( ) { result = FlowState:: full ( ) }
155
+
156
+ override FlowState:: State getAState ( ) { result instanceof FlowState:: Full }
96
157
}
97
158
}
0 commit comments