Python: Add more tests of django responses

They clearly shouldn't all be XSS sinks
This commit is contained in:
Rasmus Wriedt Larsen
2020-05-18 16:56:47 +02:00
parent 14664be467
commit 72ea4ff0dc
5 changed files with 93 additions and 21 deletions

View File

@@ -8,6 +8,11 @@
| views_1x.py:45:25:45:70 | django.Response(...) | externally controlled string |
| views_1x.py:66:25:66:55 | django.Response(...) | externally controlled string |
| views_1x.py:75:25:75:33 | django.Response(...) | externally controlled string |
| views_1x.py:85:25:85:55 | django.Response(...) | externally controlled string |
| views_1x.py:90:25:90:33 | django.Response(...) | externally controlled string |
| views_1x.py:94:25:94:58 | django.Response(...) | externally controlled string |
| views_1x.py:99:33:99:55 | django.Response(...) | externally controlled string |
| views_1x.py:103:33:103:55 | django.Response(...) | externally controlled string |
| views_2x_3x.py:8:25:8:63 | django.Response(...) | externally controlled string |
| views_2x_3x.py:12:25:12:52 | django.Response(...) | externally controlled string |
| views_2x_3x.py:16:25:16:53 | django.Response(...) | externally controlled string |
@@ -21,3 +26,8 @@
| views_2x_3x.py:82:25:82:69 | django.Response(...) | externally controlled string |
| views_2x_3x.py:85:25:85:64 | django.Response(...) | externally controlled string |
| views_2x_3x.py:88:25:88:32 | django.Response(...) | externally controlled string |
| views_2x_3x.py:106:25:106:55 | django.Response(...) | externally controlled string |
| views_2x_3x.py:111:25:111:33 | django.Response(...) | externally controlled string |
| views_2x_3x.py:115:25:115:58 | django.Response(...) | externally controlled string |
| views_2x_3x.py:120:33:120:55 | django.Response(...) | externally controlled string |
| views_2x_3x.py:124:33:124:55 | django.Response(...) | externally controlled string |

View File

@@ -1,6 +1,6 @@
"""test of views for Django 1.x"""
from django.conf.urls import patterns, url
from django.http.response import HttpResponse
from django.http.response import HttpResponse, HttpResponseRedirect, JsonResponse, HttpResponseNotFound
from django.views.generic import View
@@ -77,3 +77,27 @@ def kw_args(request):
urlpatterns = [
url(view=kw_args, regex=r'^kw_args$')
]
# Not an XSS sink, since the Content-Type is not "text/html"
# FP reported in https://github.com/github/codeql-python-team/issues/38
def fp_json_response(request):
# implicitly sets Content-Type to "application/json"
return JsonResponse({"foo": request.GET.get("foo")})
# Not an XSS sink, since the Content-Type is not "text/html"
def fp_manual_json_response(request):
json_data = '{"json": "{}"}'.format(request.GET.get("foo"))
return HttpResponse(json_data, content_type="application/json")
# Not an XSS sink, since the Content-Type is not "text/html"
def fp_manual_content_type(reuqest):
return HttpResponse('<img src="0" onerror="alert(1)">', content_type="text/plain")
# XSS FP reported in https://github.com/github/codeql/issues/3466
# Note: This should be a open-redirect sink, but not a XSS sink.
def fp_redirect(request):
return HttpResponseRedirect(request.GET.get("next"))
# Ensure that subclasses are still vuln to XSS
def tp_not_found(request):
return HttpResponseNotFound(request.GET.get("name"))

View File

@@ -1,6 +1,6 @@
"""testing views for Django 2.x and 3.x"""
from django.urls import path, re_path
from django.http import HttpResponse
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse, HttpResponseNotFound
from django.views import View
@@ -99,24 +99,26 @@ urlpatterns = [
]
################################################################################
# Not an XSS sink, since the Content-Type is not "text/html"
# FP reported in https://github.com/github/codeql-python-team/issues/38
def fp_json_response(request):
# implicitly sets Content-Type to "application/json"
return JsonResponse({"foo": request.GET.get("foo")}) # TODO
# Not an XSS sink, since the Content-Type is not "text/html"
def fp_manual_json_response(request):
json_data = '{"json": "{}"}'.format(request.GET.get("foo"))
return HttpResponse(json_data, content_type="application/json") # TODO
# We should abort if a decorator is used. As demonstrated below, anything might happen
# Not an XSS sink, since the Content-Type is not "text/html"
def fp_manual_content_type(reuqest):
return HttpResponse('<img src="0" onerror="alert(1)">', content_type="text/plain") # TODO
# def reverse_kwargs(f):
# @wraps(f)
# def f_(*args, **kwargs):
# new_kwargs = dict()
# for key, value in kwargs.items():
# new_kwargs[key[::-1]] = value
# return f(*args, **new_kwargs)
# return f_
# XSS FP reported in https://github.com/github/codeql/issues/3466
# Note: This should be a open-redirect sink, but not a XSS sink.
def fp_redirect(request):
return HttpResponseRedirect(request.GET.get("next")) # TODO
# @reverse_kwargs
# def decorators_can_do_anything(request, oof, foo=None):
# return HttpResponse('This is a mess'[::-1])
# urlpatterns = [
# path('rev/<foo>', decorators_can_do_anything),
# ]
# Ensure that subclasses are still vuln to XSS
def tp_not_found(request):
return HttpResponseNotFound(request.GET.get("name"))

View File

@@ -1,2 +1,2 @@
from .response import HttpResponse
from .response import *
from .request import HttpRequest

View File

@@ -1,2 +1,38 @@
class HttpResponse(object):
class HttpResponseBase(object):
status_code = 200
class HttpResponse(HttpResponseBase):
pass
class HttpResponseRedirectBase(HttpResponse):
pass
class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
status_code = 301
class HttpResponseRedirect(HttpResponseRedirectBase):
status_code = 302
class HttpResponseNotFound(HttpResponse):
status_code = 404
class JsonResponse(HttpResponse):
def __init__(
self,
data,
encoder=...,
safe=True,
json_dumps_params=None,
**kwargs
):
# fake code to represent what is going on :)
kwargs.setdefault("content_type", "application/json")
data = str(data)
super().__init__(content=data, **kwargs)