@@ -13,38 +13,92 @@ private import codeql.ruby.dataflow.BarrierGuards
1313module CodeInjection {
1414 /** Flow states used to distinguish whether an attacker controls the entire string. */
1515 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 { }
1845
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 { }
2150 }
2251
2352 /**
2453 * A data flow source for "Code injection" vulnerabilities.
2554 */
2655 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+
2764 /** 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+ }
2968 }
3069
3170 /**
3271 * A data flow sink for "Code injection" vulnerabilities.
3372 */
3473 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+
3582 /** 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 ( ) }
3784 }
3885
3986 /**
4087 * A sanitizer for "Code injection" vulnerabilities.
4188 */
4289 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+
4397 /**
4498 * Gets a flow state for which this is a sanitizer.
4599 * Sanitizes all states if the result is empty.
46100 */
47- DataFlow :: FlowState getAFlowState ( ) { none ( ) }
101+ FlowState :: State getAState ( ) { none ( ) }
48102 }
49103
50104 /**
@@ -67,12 +121,17 @@ module CodeInjection {
67121
68122 CodeExecutionAsSink ( ) { this = c .getCode ( ) }
69123
70- /** Gets a flow state for which this is a sink. */
71- override DataFlow:: FlowState getAFlowState ( ) {
124+ deprecated override DataFlow:: FlowState getAFlowState ( ) {
72125 if c .runsArbitraryCode ( )
73126 then result = [ FlowState:: substring ( ) , FlowState:: full ( ) ] // If it runs arbitrary code then it's always vulnerable.
74127 else result = FlowState:: full ( ) // If it "just" loads something, then it's only vulnerable if the attacker controls the entire string.
75128 }
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+ }
76135 }
77136
78137 private import codeql.ruby.AST as Ast
@@ -92,6 +151,8 @@ module CodeInjection {
92151 )
93152 }
94153
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 }
96157 }
97158}
0 commit comments