XSS Security in Django

You know output encoding is most important thing when topic comes to XSS. Today I’ve decided to write a article about how to secure your Django application against XSS vulnerabilities. Handing XSS cases with Django is more easy than other frameworks. Your Django app is approximately secure against XSS even if you developed it without security  mind. Therefore Django is try to encode specific characters in order to prevent yourself from cross-site scripting. But Django going to be fail  under the some circumstances.

PS : If you think any part of this article needs update or changes, feel free to leave comment. 

Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design.

Django Default Output Encoding Mechanism

Django try to encode some dangerous characters  in order to prevent XSS vulnerability. Let see which characters are going to be encoded when you try to print it out at htmls.

And home.html file.

We all know that most common XSS cases related to quotes, less-bigger than sign and brackets. Therefore we need to know which characters are going to be encoded. In order to understand that I create following URL’-“-->-<-(-)-{-}-%26

Result is here.

I've append dash after every single characters so we can easily understand which output belongs to which character.

As a result, we've learned that Django only cares following characters.

  • Single and double quote.
  • Less-bigger than signs.

Test Django Output against Different Context Based XSS Cases

We all know XSS vulnerabilities can be appear in different contexts which means that each context have individual payload / approach. I've create following html file in order to show differences to you.

Let's send same request again and analyze output context by context.

Html Context

As you can see < and > sings are encoded by Django. Therefore we are not able to initiate new html tag like <img or <script> . You Django application is secure against HTML Context Based XSS Vulnerabilities.

Attribute Context

Single and double quotes are encoded which  is good for us. Attribute context based XSS vulnerabilities appears because lack of single/double output encoding. But this is not enough. We already know that Django doesnt encode  back-tick  ( ) which is cause XSS vulnerability in specific IE version.

Let send following request to Django application and analyze output.

I’ve omitted other context and leave attribute context sample alone. As you can see    are not encoded over there. This doesn’t means anything to Firefox and Chromes but it does for old version of IE. Because old IE browsers treat it as a valid separator.

 Javascript Context

Single, double and less-bigger than sings are encoded. Which means we cant reach out of variable values. Because we need single or double quotes but they are already encoded by Django. Also we are not able to end script tags because of > and < are encoded too.

All of these payload will be failed because of Django encode but there is some specials cases about Javascript context.

Keeping old things is bad …

Let assume that developers comment out some part of JS codes. I’ve seen this too many times during penetration test.

It just comment outed. This codes are vulnerability because of comment out.

Boom.  The trick is new line character. %0A is encoded new line character. When python see that it create new and continue to printing values . As an attacker we avoid comment out area and reach to javascript context. Last double slash is for prevention syntax error.

 Style Context

Obviously Django can be vulnerable against stylish XSS. Because Django doesn’t encodes ( and ) . Let’ me show you some payload that can successfully exploit XSS vulnerability. Please send following request to the django app.

I’ve omitted other contexts again. Now you see payload reflected inside style attribute of div tag and this is valid XSS vulnerability works on Internet Explorer.


If you use default output methods in everywhere, your Django app will be vulnerable against XSS. From previous section we know back-tick can be dangerous on attributes. We should encode it out at attribute context. Also we’ve learned that new line characters is dangerous under the circumstances, we should encode it too. And Bracket is can be dangerous too when input reflected inside style context.

I’ve developed 3 differend function. Please read instructions.

Furter and detailed information can be found at Ashar’s work and PHP implementation :

  • Andrey

    Nice article, but function-based views makes me sad :)