@@ -31,7 +31,7 @@ class WerkzeugHeaderCall extends DataFlow::CallCfgNode {
31
31
DataFlow:: Node getHeaderInputNode ( ) { result = this .getArg ( 1 ) }
32
32
}
33
33
34
- class FlaskHeaderCall extends DataFlow:: CallCfgNode {
34
+ class FlaskHeaderCall extends DataFlow:: Node {
35
35
DataFlow:: Node headerInputNode ;
36
36
37
37
FlaskHeaderCall ( ) {
@@ -44,39 +44,108 @@ class FlaskHeaderCall extends DataFlow::CallCfgNode {
44
44
responseMethod .getObject ( ) .getALocalSource ( ) = headerInstance and
45
45
sinkDeclaration .getATarget ( ) = responseMethod .asExpr ( ) .getParentNode ( ) and
46
46
headerInputNode .asExpr ( ) = sinkDeclaration .getValue ( ) and
47
- this .getFunction ( ) = responseMethod
47
+ this .asExpr ( ) = sinkDeclaration . getATarget ( )
48
48
)
49
49
}
50
50
51
51
DataFlow:: Node getHeaderInputNode ( ) { result = headerInputNode }
52
52
}
53
53
54
- class FlaskMakeResponse extends DataFlow:: Node {
55
- FlaskMakeResponse ( ) {
54
+ class FlaskMakeResponseCall extends DataFlow:: Node {
55
+ DataFlow:: Node headerInputNode ;
56
+
57
+ FlaskMakeResponseCall ( ) {
56
58
exists (
57
59
DataFlow:: CallCfgNode headerInstance , DataFlow:: AttrRead responseMethod ,
58
60
AssignStmt sinkDeclaration
59
61
|
60
62
headerInstance = API:: moduleImport ( "flask" ) .getMember ( "make_response" ) .getACall ( ) and
61
63
responseMethod .getAttributeName ( ) = "headers" and
62
64
responseMethod .getObject ( ) .getALocalSource ( ) = headerInstance and
63
- (
64
- sinkDeclaration .getATarget ( ) = responseMethod .asExpr ( ) .getParentNode ( ) and
65
- this .asExpr ( ) = sinkDeclaration .getValue ( )
66
- )
67
- //or
68
- //extendMethod.getAttributeName() = "extend" and
69
- //extendMethod.getObject().getALocalSource() = responseMethod and
70
- //this = extendMethod.(DataFlow::CallCfgNode).getArg(0)
65
+ sinkDeclaration .getATarget ( ) = responseMethod .asExpr ( ) .getParentNode ( ) and
66
+ this .asExpr ( ) = sinkDeclaration .getATarget ( ) and
67
+ headerInputNode .asExpr ( ) = sinkDeclaration .getValue ( )
68
+ )
69
+ }
70
+
71
+ DataFlow:: Node getHeaderInputNode ( ) { result = headerInputNode }
72
+ }
73
+
74
+ class FlaskMakeResponseExtendCall extends DataFlow:: CallCfgNode {
75
+ DataFlow:: Node headerInputNode ;
76
+
77
+ FlaskMakeResponseExtendCall ( ) {
78
+ exists (
79
+ DataFlow:: CallCfgNode headerInstance , DataFlow:: AttrRead responseMethod ,
80
+ DataFlow:: AttrRead extendMethod
81
+ |
82
+ headerInstance = API:: moduleImport ( "flask" ) .getMember ( "make_response" ) .getACall ( ) and
83
+ responseMethod .getAttributeName ( ) = "headers" and
84
+ responseMethod .getObject ( ) .getALocalSource ( ) = headerInstance and
85
+ extendMethod .getAttributeName ( ) = "extend" and
86
+ extendMethod .getObject ( ) .getALocalSource ( ) = responseMethod and
87
+ this .getFunction ( ) = extendMethod and
88
+ headerInputNode = this .getArg ( 0 )
71
89
)
72
90
}
91
+
92
+ DataFlow:: Node getHeaderInputNode ( ) { result = headerInputNode }
93
+ }
94
+
95
+ class FlaskResponseArg extends DataFlow:: CallCfgNode {
96
+ DataFlow:: Node headerInputNode ;
97
+
98
+ FlaskResponseArg ( ) {
99
+ this = API:: moduleImport ( "flask" ) .getMember ( "Response" ) .getACall ( ) and
100
+ headerInputNode = this .getArgByName ( "headers" )
101
+ }
102
+
103
+ DataFlow:: Node getHeaderInputNode ( ) { result = headerInputNode }
104
+ }
105
+
106
+ class DjangoResponseSetItemCall extends DataFlow:: CallCfgNode {
107
+ DjangoResponseSetItemCall ( ) {
108
+ exists ( DataFlow:: AttrRead setItemMethod |
109
+ this .getFunction ( ) = setItemMethod and
110
+ setItemMethod .getObject ( ) .getALocalSource ( ) =
111
+ API:: moduleImport ( "django" ) .getMember ( "http" ) .getMember ( "HttpResponse" ) .getACall ( ) and
112
+ setItemMethod .getAttributeName ( ) = "__setitem__"
113
+ )
114
+ }
115
+
116
+ DataFlow:: Node getHeaderInputNode ( ) { result = this .getArg ( 1 ) }
117
+ }
118
+
119
+ class DjangoResponseAssignCall extends DataFlow:: Node {
120
+ DataFlow:: Node headerInputNode ;
121
+
122
+ DjangoResponseAssignCall ( ) {
123
+ exists (
124
+ DataFlow:: CallCfgNode headerInstance , Subscript responseMethod , DataFlow:: Node responseToNode ,
125
+ AssignStmt sinkDeclaration
126
+ |
127
+ headerInstance =
128
+ API:: moduleImport ( "django" ) .getMember ( "http" ) .getMember ( "HttpResponse" ) .getACall ( ) and
129
+ responseMethod .getValue ( ) = responseToNode .asExpr ( ) and
130
+ responseToNode .getALocalSource ( ) .asExpr ( ) = headerInstance .asExpr ( ) and
131
+ sinkDeclaration .getATarget ( ) = responseMethod and
132
+ this .asExpr ( ) = sinkDeclaration .getATarget ( ) and
133
+ headerInputNode .asExpr ( ) = sinkDeclaration .getValue ( )
134
+ )
135
+ }
136
+
137
+ DataFlow:: Node getHeaderInputNode ( ) { result = headerInputNode }
73
138
}
74
139
75
140
class HeaderInjectionSink extends DataFlow:: Node {
76
141
HeaderInjectionSink ( ) {
77
- this instanceof WerkzeugHeaderCall or
78
- this instanceof FlaskHeaderCall or
79
- this instanceof FlaskMakeResponse
142
+ this = any ( WerkzeugHeaderCall a ) .getHeaderInputNode ( ) or
143
+ this = any ( FlaskHeaderCall a ) .getHeaderInputNode ( ) or
144
+ this = any ( FlaskMakeResponseCall a ) .getHeaderInputNode ( ) or
145
+ this = any ( FlaskMakeResponseExtendCall a ) .getHeaderInputNode ( ) or
146
+ this = any ( FlaskResponseArg a ) .getHeaderInputNode ( ) or
147
+ this = any ( DjangoResponseSetItemCall a ) .getHeaderInputNode ( ) or
148
+ this = any ( DjangoResponseAssignCall a ) .getHeaderInputNode ( )
80
149
}
81
150
}
82
151
0 commit comments