@@ -14,6 +14,7 @@ private import semmle.python.frameworks.Stdlib
14
14
private import semmle.python.regex
15
15
private import semmle.python.frameworks.internal.PoorMansFunctionResolution
16
16
private import semmle.python.frameworks.internal.SelfRefMixin
17
+ private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
17
18
18
19
/**
19
20
* Provides models for the `django` PyPI package.
@@ -340,19 +341,30 @@ private module Django {
340
341
/**
341
342
* Taint propagation for `django.utils.datastructures.MultiValueDict`.
342
343
*/
344
+ private class InstanceTaintSteps extends InstanceTaintStepsHelper {
345
+ InstanceTaintSteps ( ) { this = "django.utils.datastructures.MultiValueDict" }
346
+
347
+ override DataFlow:: Node getInstance ( ) { result = instance ( ) }
348
+
349
+ override string getAttributeName ( ) { none ( ) }
350
+
351
+ override string getMethodName ( ) {
352
+ result in [ "getlist" , "lists" , "popitem" , "dict" , "urlencode" ]
353
+ }
354
+
355
+ override string getAsyncMethodName ( ) { none ( ) }
356
+ }
357
+
358
+ /**
359
+ * Extra taint propagation for `django.utils.datastructures.MultiValueDict`, not covered by `InstanceTaintSteps`.
360
+ */
343
361
private class AdditionalTaintStep extends TaintTracking:: AdditionalTaintStep {
344
362
override predicate step ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
345
363
// class instantiation
346
364
exists ( ClassInstantiation call |
347
365
nodeFrom = call .getArg ( 0 ) and
348
366
nodeTo = call
349
367
)
350
- or
351
- // normal (non-async) methods
352
- nodeFrom = instance ( ) and
353
- nodeTo
354
- .( DataFlow:: MethodCallNode )
355
- .calls ( nodeFrom , [ "getlist" , "lists" , "popitem" , "dict" , "urlencode" ] )
356
368
}
357
369
}
358
370
}
@@ -388,15 +400,20 @@ private module Django {
388
400
/**
389
401
* Taint propagation for `django.core.files.uploadedfile.UploadedFile`.
390
402
*/
391
- private class AdditionalTaintStep extends TaintTracking:: AdditionalTaintStep {
392
- override predicate step ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
393
- // Attributes
394
- nodeFrom = instance ( ) and
395
- nodeTo .( DataFlow:: AttrRead ) .getObject ( ) = nodeFrom and
396
- nodeTo .( DataFlow:: AttrRead ) .getAttributeName ( ) in [
403
+ private class InstanceTaintSteps extends InstanceTaintStepsHelper {
404
+ InstanceTaintSteps ( ) { this = "django.core.files.uploadedfile.UploadedFile" }
405
+
406
+ override DataFlow:: Node getInstance ( ) { result = instance ( ) }
407
+
408
+ override string getAttributeName ( ) {
409
+ result in [
397
410
"content_type" , "content_type_extra" , "content_type_extra" , "charset" , "name" , "file"
398
411
]
399
412
}
413
+
414
+ override string getMethodName ( ) { none ( ) }
415
+
416
+ override string getAsyncMethodName ( ) { none ( ) }
400
417
}
401
418
402
419
/** A file-like object instance that originates from a `UploadedFile`. */
@@ -436,13 +453,16 @@ private module Django {
436
453
/**
437
454
* Taint propagation for `django.urls.ResolverMatch`.
438
455
*/
439
- private class AdditionalTaintStep extends TaintTracking:: AdditionalTaintStep {
440
- override predicate step ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
441
- // Attributes
442
- nodeFrom = instance ( ) and
443
- nodeTo .( DataFlow:: AttrRead ) .getObject ( ) = nodeFrom and
444
- nodeTo .( DataFlow:: AttrRead ) .getAttributeName ( ) in [ "args" , "kwargs" ]
445
- }
456
+ private class InstanceTaintSteps extends InstanceTaintStepsHelper {
457
+ InstanceTaintSteps ( ) { this = "django.urls.ResolverMatch" }
458
+
459
+ override DataFlow:: Node getInstance ( ) { result = instance ( ) }
460
+
461
+ override string getAttributeName ( ) { result in [ "args" , "kwargs" ] }
462
+
463
+ override string getMethodName ( ) { none ( ) }
464
+
465
+ override string getAsyncMethodName ( ) { none ( ) }
446
466
}
447
467
}
448
468
}
@@ -747,15 +767,43 @@ private module PrivateDjango {
747
767
/**
748
768
* Taint propagation for `django.http.request.HttpRequest`.
749
769
*/
770
+ private class InstanceTaintSteps extends InstanceTaintStepsHelper {
771
+ InstanceTaintSteps ( ) { this = "django.http.request.HttpRequest" }
772
+
773
+ override DataFlow:: Node getInstance ( ) { result = instance ( ) }
774
+
775
+ override string getAttributeName ( ) {
776
+ result in [
777
+ // str / bytes
778
+ "body" , "path" , "path_info" , "method" , "encoding" , "content_type" ,
779
+ // django.http.QueryDict
780
+ "GET" , "POST" ,
781
+ // dict[str, str]
782
+ "content_params" , "COOKIES" ,
783
+ // dict[str, Any]
784
+ "META" ,
785
+ // HttpHeaders (case insensitive dict-like)
786
+ "headers" ,
787
+ // MultiValueDict[str, UploadedFile]
788
+ "FILES" ,
789
+ // django.urls.ResolverMatch
790
+ "resolver_match"
791
+ ]
792
+ // TODO: Handle that a HttpRequest is iterable
793
+ }
794
+
795
+ override string getMethodName ( ) {
796
+ result in [ "get_full_path" , "get_full_path_info" , "read" , "readline" , "readlines" ]
797
+ }
798
+
799
+ override string getAsyncMethodName ( ) { none ( ) }
800
+ }
801
+
802
+ /**
803
+ * Extra taint propagation for `django.http.request.HttpRequest`, not covered by `InstanceTaintSteps`.
804
+ */
750
805
private class AdditionalTaintStep extends TaintTracking:: AdditionalTaintStep {
751
806
override predicate step ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
752
- // normal (non-async) methods
753
- nodeFrom = django:: http:: request:: HttpRequest:: instance ( ) and
754
- nodeTo
755
- .( DataFlow:: MethodCallNode )
756
- .calls ( nodeFrom ,
757
- [ "get_full_path" , "get_full_path_info" , "read" , "readline" , "readlines" ] )
758
- or
759
807
// special handling of the `build_absolute_uri` method, see
760
808
// https://docs.djangoproject.com/en/3.0/ref/request-response/#django.http.HttpRequest.build_absolute_uri
761
809
exists ( DataFlow:: AttrRead attr , DataFlow:: CallCfgNode call , DataFlow:: Node instance |
@@ -775,27 +823,6 @@ private module PrivateDjango {
775
823
nodeFrom = call .getArgByName ( "location" )
776
824
)
777
825
)
778
- or
779
- // Attributes
780
- nodeFrom = django:: http:: request:: HttpRequest:: instance ( ) and
781
- nodeTo .( DataFlow:: AttrRead ) .getObject ( ) = nodeFrom and
782
- nodeTo .( DataFlow:: AttrRead ) .getAttributeName ( ) in [
783
- // str / bytes
784
- "body" , "path" , "path_info" , "method" , "encoding" , "content_type" ,
785
- // django.http.QueryDict
786
- "GET" , "POST" ,
787
- // dict[str, str]
788
- "content_params" , "COOKIES" ,
789
- // dict[str, Any]
790
- "META" ,
791
- // HttpHeaders (case insensitive dict-like)
792
- "headers" ,
793
- // MultiValueDict[str, UploadedFile]
794
- "FILES" ,
795
- // django.urls.ResolverMatch
796
- "resolver_match"
797
- ]
798
- // TODO: Handle that a HttpRequest is iterable
799
826
}
800
827
}
801
828
0 commit comments