74 lines
2.5 KiB
Plaintext
74 lines
2.5 KiB
Plaintext
=== How to fix it in Django
|
|
|
|
The following code is vulnerable to cross-site scripting because it returns an HTML response that contains user input.
|
|
|
|
If you do not intend to send HTML code to clients, the vulnerability can be fixed by specifying the type of data returned in the response.
|
|
For example, you can use the `JsonResponse` class to return JSON messages securely.
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,python,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
from django.http import HttpResponse
|
|
import json
|
|
|
|
def index(request):
|
|
json = json.dumps({ "data": request.GET.get("input") })
|
|
return HttpResponse(json)
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,python,diff-id=1,diff-type=compliant]
|
|
----
|
|
from django.http import JsonResponse
|
|
|
|
def index(request):
|
|
json = { "data": request.GET.get("input") }
|
|
return JsonResponse(json)
|
|
----
|
|
|
|
It is also possible to set the content-type manually with the `content_type` parameter when creating an `HttpResponse` object.
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,python,diff-id=2,diff-type=noncompliant]
|
|
----
|
|
from django.http import HttpResponse
|
|
|
|
def index(request):
|
|
return HttpResponse(request.GET.get("input"))
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,python,diff-id=2,diff-type=compliant]
|
|
----
|
|
from django.http import HttpResponse
|
|
|
|
def index(request):
|
|
return HttpResponse(request.GET.get("input"), content_type="text/plain")
|
|
----
|
|
|
|
=== How does this work?
|
|
|
|
If the HTTP response consists of HTML code, it is highly recommended to use a template engine like https://docs.djangoproject.com/en/4.0/topics/templates/[Django's template system] to generate it.
|
|
The Django template engine separates the view from the business logic and automatically encodes the output of variables, drastically reducing the risk of cross-site scripting vulnerabilities.
|
|
|
|
If you do not intend to send HTML code to clients, the vulnerability can be fixed by telling them what data they are receiving with the `content-type` HTTP header.
|
|
This header tells the browser that the response does not contain HTML code and should not be parsed and interpreted as HTML.
|
|
Thus, the response is not vulnerable to reflected cross-site scripting.
|
|
|
|
For example, setting the Content-Type HTTP header to `text/plain` allows to safely reflect user input, because browsers will not try to parse and execute the response.
|
|
|
|
=== Pitfalls
|
|
|
|
include::../../common/pitfalls/content-types.adoc[]
|
|
|
|
include::../../common/pitfalls/validation.adoc[]
|
|
|
|
=== Going the extra mile
|
|
|
|
include::../../common/extra-mile/csp.adoc[]
|
|
|