TechGuard Blog | TechGuard Security

How to Prevent XSS in Python Based Web Applications

Written by Noland Crane | Mar 28, 2022 4:38:28 PM

Cross-site scripting attacks against websites are practically as old as the internet itself. It is very easy to shake off Cross-Site Scripting (XSS) as low impact vulnerability because it is often demonstrated by “popping” an alert box.

This may seem trivial to the uninformed, but this pop-up alert means that an attacker is able to execute arbitrary JavaScript on the end user’s browser via your vulnerable application. Crafty attacks can steal cookies, hook web browsers to an exploitation framework, or be a catalyst for social engineering attacks. There is a good reason why XSS was included in the OWASP Top 10 in 2017. We will discuss how to defend python applications from this vulnerability, but these concepts are the same in all languages.

The Scenario

I have created a simple web application called “Farmers Lonely Dating” using Django which is a python-based web framework.


This application functions by allowing a lonely farmer to submit his name and the number of acres he owns.

The application responds by displaying text on the screen saying, “My name is [Name]and I own [acres] of land”. This type of functionality is a prime target for reflected cross-site scripting attacks since user input is presented back to the browser.

 

Below, is the backend Python code that operates the application functionality. All this code does is stores the post data into a variable and then use it to render an HTML page back to the user that contains the raw user input from the post request.


Exploiting a Lonely Farmer

This application was intentionally made vulnerable to XSS because by default Django protects against XSS attacks. If we enter in “<script>alert(1);</script>” in either one of the fields arbitrary JavaScript will be executed on the user’s browser. To iterate again, XSS attacks the user via a vulnerable web application.



Principles To Defend Against Cross-Site Scripting

Never Trust User Input

When developing secure code, it is imperative that user input is never to be trusted. This may make it sound like people are out pwn you via code injection attacks, but in reality many are.

Input Sanitization

This type of defense involves filtering user input when it is received based on what is expected or what valid input should be.


In the code above, the is a variable named “badchar” that is used to delete characters such as %*+ -/;<=>^ from user input. To test this “<script>alert(1)</script>” was entered as the name and as evident from the output this code stopped the XSS attack!

This method works well but is not always full proof. It is possible for develops to miss dangerous characters. Additionally, this method is not viable if for some reason these dangerous characters should be included in the expected input. I.E. Elon Musk’s son.

Encoding data on output

This type of defense operates by encoding dangerous characters into safe Html entities. For example <> would be encoded to &lt;&gt; before being rendered to the browser.


This method is typically the best method to employ because even if dangerous characters make it past server-side filtering, the encoding ensures they will not be able to cause damage.

 

For the sake of all the lonely farmers out there, correction, your end-users, ensure that developers of web applications are well versed in the OWASP top 10 and how to defend their applications from these types of attacks. Link to OWASP official site: OWASP Foundation | Open Source Foundation for Application Security Additionally proper security testing of web applications is also required in the development cycle to ensure that vulnerabilities will not make it to production where they can be exploited.