Snippet

🔖 Day17 - Markdown DIY prevent XSS attack (Part 1)

2018 - 06 - 26

In Django, there is CSRF protection against the Cross-Site Request Forgery. It is so handy which reduces our workloads on security issues.
However, XSS attack is also a problem. So what is XSS? Well, simply speaking, it is about some sneaky attackers who found out your site contains fields that enable scripts, e.g. comments with scripts running. These sneaky guys then post some scripts such as html or javascript. When a visitor come in and load the comment page, the scripts are invoked. That innocent visitor is now vulnerable to privacy exposure which may be further sent to attackers in background.
This picture from Incapsula briefly sums up.

1. [Django safe filter]
So, what exactly does it deal with Django site? While rendering fields in a template, we use {{ field }}. To enable scripts on certain field, a template filter safe can be used, e.g. {{ field | safe }}. Hence, any scripts in this field will not be autoescaped but able to run smoothly. Consequently, the page containing this field is now susceptible to XSS attacks.
Say you have a comment session with scripts enabled and is constructed with
form.py:

Nothing in form.py or views.py is going to deal with XSS. Thus, we have to do it on our own. There, is what a markdown tool can help. Of course, you can clone any markdown tool from github, but in this demo I am going to build my own.

2. [buttons for using scripts]
We love to have text-decorations and insert links while typing online. To avoid users from typing these common scripts manually, (and to assist those not familiar with HTML tags), we can create some buttons for them.
Firstly, head to template :

Such that when users click on either button, this will add corresponding tag, e.g. [bold]Text Here...[/bold], into the content field. #id_content should be the id of your content field as long as your field name is set as content in form.py .

In this snippet, we named a new variable temp to validate first. After that, run the form method updateContent and return the new content to a new variable content . Since we need to modify the form details before saving, we have to call temp.save(commit=False) . Lastly, assign content to form.content and de facto save the form.

5. [escaping the angle brackets]
It is time to check out your comment page in browser. There should be the bold and link buttons, which add tags to content field on click. Through submitting the comment, these tags become proper HTML tags, which can be loaded on the page with {{ field | safe }}.
But what we have done is just providing alternatives to users, not restricting them from typing their own scripts! Oh, this is cake now.
What we have done so far is created some tags for masking proper HTML tags. Similary, we can mask users' angle brackets via the same old form method.
Head back to form.py and add 2 more lines:

See? It's done! By converting the angle brackets into their corresponding HTML entities, whenever users type their own scripts, it fails to run. Instead, the brackets will show up as normal brackets in the viewing template.