Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ab607b8

Browse files
committed
Python: Add redirect modeling for Django
1 parent aea974e commit ab607b8

2 files changed

Lines changed: 16 additions & 6 deletions

File tree

python/ql/src/semmle/python/frameworks/Django.qll

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,8 @@ private module Django {
724724
*
725725
* Use the predicate `HttpResponseRedirect::instance()` to get references to instances of `django.http.response.HttpResponseRedirect`.
726726
*/
727-
abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { }
727+
abstract class InstanceSource extends HttpResponse::InstanceSource,
728+
HTTP::Server::HttpRedirectResponse::Range, DataFlow::Node { }
728729

729730
/** A direct instantiation of `django.http.response.HttpResponseRedirect`. */
730731
private class ClassInstantiation extends InstanceSource, DataFlow::CfgNode {
@@ -739,6 +740,10 @@ private module Django {
739740
result.asCfgNode() in [node.getArg(1), node.getArgByName("content")]
740741
}
741742

743+
override DataFlow::Node getRedirectLocation() {
744+
result.asCfgNode() in [node.getArg(0), node.getArgByName("redirect_to")]
745+
}
746+
742747
// How to support the `headers` argument here?
743748
override DataFlow::Node getMimetypeOrContentTypeArg() { none() }
744749

@@ -790,7 +795,8 @@ private module Django {
790795
*
791796
* Use the predicate `HttpResponsePermanentRedirect::instance()` to get references to instances of `django.http.response.HttpResponsePermanentRedirect`.
792797
*/
793-
abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { }
798+
abstract class InstanceSource extends HttpResponse::InstanceSource,
799+
HTTP::Server::HttpRedirectResponse::Range, DataFlow::Node { }
794800

795801
/** A direct instantiation of `django.http.response.HttpResponsePermanentRedirect`. */
796802
private class ClassInstantiation extends InstanceSource, DataFlow::CfgNode {
@@ -805,6 +811,10 @@ private module Django {
805811
result.asCfgNode() in [node.getArg(1), node.getArgByName("content")]
806812
}
807813

814+
override DataFlow::Node getRedirectLocation() {
815+
result.asCfgNode() in [node.getArg(0), node.getArgByName("redirect_to")]
816+
}
817+
808818
// How to support the `headers` argument here?
809819
override DataFlow::Node getMimetypeOrContentTypeArg() { none() }
810820

python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,22 @@ def safe__manual_content_type(request):
1919
# Note: This should be an open-redirect sink, but not an XSS sink.
2020
def or__redirect(request):
2121
next = request.GET.get("next")
22-
return HttpResponseRedirect(next) # $HttpResponse mimetype=text/html MISSING: HttpRedirectResponse redirectLocation=next
22+
return HttpResponseRedirect(next) # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation=next
2323

2424
def information_exposure_through_redirect(request, as_kw=False, perm_redirect=False):
2525
# This is a contrived example, but possible
2626
private = "private"
2727
next = request.GET.get("next")
2828
if as_kw:
29-
return HttpResponseRedirect(next, content=private) # $HttpResponse mimetype=text/html responseBody=private MISSING: HttpRedirectResponse redirectLocation=next
29+
return HttpResponseRedirect(next, content=private) # $HttpResponse mimetype=text/html responseBody=private HttpRedirectResponse redirectLocation=next
3030
else:
31-
return HttpResponseRedirect(next, private) # $ HttpResponse mimetype=text/html responseBody=private MISSING: HttpRedirectResponse redirectLocation=next
31+
return HttpResponseRedirect(next, private) # $ HttpResponse mimetype=text/html responseBody=private HttpRedirectResponse redirectLocation=next
3232

3333

3434
def perm_redirect(request):
3535
private = "private"
3636
next = request.GET.get("next")
37-
return HttpResponsePermanentRedirect(next, private) # $ HttpResponse mimetype=text/html responseBody=private MISSING: HttpRedirectResponse redirectLocation=next
37+
return HttpResponsePermanentRedirect(next, private) # $ HttpResponse mimetype=text/html responseBody=private HttpRedirectResponse redirectLocation=next
3838

3939

4040
def redirect_through_normal_response(request):

0 commit comments

Comments
 (0)