@@ -33,7 +33,7 @@ private module Django {
3333 * WARNING: Only holds for a few predefined attributes.
3434 */
3535 private DataFlow:: Node django_attr ( DataFlow:: TypeTracker t , string attr_name ) {
36- attr_name in [ "urls" ] and
36+ attr_name in [ "urls" , "http" ] and
3737 (
3838 t .start ( ) and
3939 result = DataFlow:: importNode ( "django" + "." + attr_name )
@@ -69,12 +69,12 @@ private module Django {
6969
7070 /** Provides models for the `django` module. */
7171 module django {
72- /** Gets a reference to the `django.urls` module. */
73- DataFlow:: Node urls ( ) { result = django_attr ( "urls" ) }
74-
7572 // -------------------------------------------------------------------------
7673 // django.urls
7774 // -------------------------------------------------------------------------
75+ /** Gets a reference to the `django.urls` module. */
76+ DataFlow:: Node urls ( ) { result = django_attr ( "urls" ) }
77+
7878 /** Provides models for the `django.urls` module */
7979 module urls {
8080 /**
@@ -132,8 +132,154 @@ private module Django {
132132 */
133133 DataFlow:: Node re_path ( ) { result = urls_attr ( "re_path" ) }
134134 }
135+
136+ // -------------------------------------------------------------------------
137+ // django.http
138+ // -------------------------------------------------------------------------
139+ /** Gets a reference to the `django.http` module. */
140+ DataFlow:: Node http ( ) { result = django_attr ( "http" ) }
141+
142+ /** Provides models for the `django.http` module */
143+ module http {
144+ /**
145+ * Gets a reference to the attribute `attr_name` of the `django.http` module.
146+ * WARNING: Only holds for a few predefined attributes.
147+ */
148+ private DataFlow:: Node http_attr ( DataFlow:: TypeTracker t , string attr_name ) {
149+ attr_name in [ "request" , "HttpRequest" ] and
150+ (
151+ t .start ( ) and
152+ result = DataFlow:: importNode ( "django.http" + "." + attr_name )
153+ or
154+ t .startInAttr ( attr_name ) and
155+ result = django:: http ( )
156+ )
157+ or
158+ // Due to bad performance when using normal setup with `http_attr(t2, attr_name).track(t2, t)`
159+ // we have inlined that code and forced a join
160+ exists ( DataFlow:: TypeTracker t2 |
161+ exists ( DataFlow:: StepSummary summary |
162+ http_attr_first_join ( t2 , attr_name , result , summary ) and
163+ t = t2 .append ( summary )
164+ )
165+ )
166+ }
167+
168+ pragma [ nomagic]
169+ private predicate http_attr_first_join (
170+ DataFlow:: TypeTracker t2 , string attr_name , DataFlow:: Node res ,
171+ DataFlow:: StepSummary summary
172+ ) {
173+ DataFlow:: StepSummary:: step ( http_attr ( t2 , attr_name ) , res , summary )
174+ }
175+
176+ /**
177+ * Gets a reference to the attribute `attr_name` of the `django.http` module.
178+ * WARNING: Only holds for a few predefined attributes.
179+ */
180+ private DataFlow:: Node http_attr ( string attr_name ) {
181+ result = http_attr ( DataFlow:: TypeTracker:: end ( ) , attr_name )
182+ }
183+
184+ // ---------------------------------------------------------------------------
185+ // django.http.request
186+ // ---------------------------------------------------------------------------
187+ /** Gets a reference to the `django.http.request` module. */
188+ DataFlow:: Node request ( ) { result = http_attr ( "request" ) }
189+
190+ /** Provides models for the `django.http.request` module. */
191+ module request {
192+ /**
193+ * Gets a reference to the attribute `attr_name` of the `django.http.request` module.
194+ * WARNING: Only holds for a few predefined attributes.
195+ */
196+ private DataFlow:: Node request_attr ( DataFlow:: TypeTracker t , string attr_name ) {
197+ attr_name in [ "HttpRequest" ] and
198+ (
199+ t .start ( ) and
200+ result = DataFlow:: importNode ( "django.http.request" + "." + attr_name )
201+ or
202+ t .startInAttr ( attr_name ) and
203+ result = django:: http:: request ( )
204+ )
205+ or
206+ // Due to bad performance when using normal setup with `request_attr(t2, attr_name).track(t2, t)`
207+ // we have inlined that code and forced a join
208+ exists ( DataFlow:: TypeTracker t2 |
209+ exists ( DataFlow:: StepSummary summary |
210+ request_attr_first_join ( t2 , attr_name , result , summary ) and
211+ t = t2 .append ( summary )
212+ )
213+ )
214+ }
215+
216+ pragma [ nomagic]
217+ private predicate request_attr_first_join (
218+ DataFlow:: TypeTracker t2 , string attr_name , DataFlow:: Node res ,
219+ DataFlow:: StepSummary summary
220+ ) {
221+ DataFlow:: StepSummary:: step ( request_attr ( t2 , attr_name ) , res , summary )
222+ }
223+
224+ /**
225+ * Gets a reference to the attribute `attr_name` of the `django.http.request` module.
226+ * WARNING: Only holds for a few predefined attributes.
227+ */
228+ private DataFlow:: Node request_attr ( string attr_name ) {
229+ result = request_attr ( DataFlow:: TypeTracker:: end ( ) , attr_name )
230+ }
231+
232+ /**
233+ * Provides models for the `django.http.request.HttpRequest` class
234+ *
235+ * See https://docs.djangoproject.com/en/3.0/ref/request-response/#httprequest-objects
236+ */
237+ module HttpRequest {
238+ /** Gets a reference to the `django.http.request.HttpRequest` class. */
239+ private DataFlow:: Node classRef ( DataFlow:: TypeTracker t ) {
240+ t .start ( ) and
241+ result = request_attr ( "HttpRequest" )
242+ or
243+ // handle django.http.HttpRequest alias
244+ t .start ( ) and
245+ result = http_attr ( "HttpRequest" )
246+ or
247+ exists ( DataFlow:: TypeTracker t2 | result = classRef ( t2 ) .track ( t2 , t ) )
248+ }
249+
250+ /** Gets a reference to the `django.http.request.HttpRequest` class. */
251+ DataFlow:: Node classRef ( ) { result = classRef ( DataFlow:: TypeTracker:: end ( ) ) }
252+
253+ /**
254+ * A source of an instance of `django.http.request.HttpRequest`.
255+ *
256+ * This can include instantiation of the class, return value from function
257+ * calls, or a special parameter that will be set when functions are call by external
258+ * library.
259+ *
260+ * Use `django::http::request::HttpRequest::instance()` predicate to get
261+ * references to instances of `django.http.request.HttpRequest`.
262+ */
263+ abstract class InstanceSource extends DataFlow:: Node { }
264+
265+ /** Gets a reference to an instance of `django.http.request.HttpRequest`. */
266+ private DataFlow:: Node instance ( DataFlow:: TypeTracker t ) {
267+ t .start ( ) and
268+ result instanceof InstanceSource
269+ or
270+ exists ( DataFlow:: TypeTracker t2 | result = instance ( t2 ) .track ( t2 , t ) )
271+ }
272+
273+ /** Gets a reference to an instance of `django.http.request.HttpRequest`. */
274+ DataFlow:: Node instance ( ) { result = instance ( DataFlow:: TypeTracker:: end ( ) ) }
275+ }
276+ }
277+ }
135278 }
136279
280+ // ---------------------------------------------------------------------------
281+ // routing modeling
282+ // ---------------------------------------------------------------------------
137283 /**
138284 * Gets a reference to the Function `func`.
139285 *
@@ -180,6 +326,10 @@ private module Django {
180326 Parameter getRequestParam ( ) { result = this .getArg ( this .getRequestParamIndex ( ) ) }
181327 }
182328
329+ abstract private class DjangoRouteSetup extends HTTP:: Server:: RouteSetup:: Range , DataFlow:: CfgNode {
330+ abstract override DjangoRouteHandler getARouteHandler ( ) ;
331+ }
332+
183333 /**
184334 * Gets the regex that is used by django to find routed parameters when using `django.urls.path`.
185335 *
@@ -194,7 +344,7 @@ private module Django {
194344 *
195345 * See https://docs.djangoproject.com/en/3.0/ref/urls/#path
196346 */
197- private class DjangoUrlsPathCall extends HTTP :: Server :: RouteSetup :: Range , DataFlow :: CfgNode {
347+ private class DjangoUrlsPathCall extends DjangoRouteSetup {
198348 override CallNode node ;
199349
200350 DjangoUrlsPathCall ( ) { node .getFunction ( ) = django:: urls:: path ( ) .asCfgNode ( ) }
@@ -251,7 +401,7 @@ private module Django {
251401 *
252402 * See https://docs.djangoproject.com/en/3.0/ref/urls/#re_path
253403 */
254- private class DjangoUrlsRePathCall extends HTTP :: Server :: RouteSetup :: Range , DataFlow :: CfgNode {
404+ private class DjangoUrlsRePathCall extends DjangoRouteSetup {
255405 override CallNode node ;
256406
257407 DjangoUrlsRePathCall ( ) { node .getFunction ( ) = django:: urls:: re_path ( ) .asCfgNode ( ) }
@@ -292,4 +442,17 @@ private module Django {
292442 )
293443 }
294444 }
445+
446+ // ---------------------------------------------------------------------------
447+ // HttpRequest taint modeling
448+ // ---------------------------------------------------------------------------
449+ class DjangoRouteHandlerRequestParam extends django:: http:: request:: HttpRequest:: InstanceSource ,
450+ RemoteFlowSource:: Range , DataFlow:: ParameterNode {
451+ DjangoRouteHandlerRequestParam ( ) {
452+ this .getParameter ( ) = any ( DjangoRouteSetup setup ) .getARouteHandler ( ) .getRequestParam ( )
453+ }
454+
455+ override string getSourceType ( ) { result = "django.http.request.HttpRequest" }
456+ }
457+
295458}
0 commit comments