If there's one thing that might seem obvious, but a lot of developers still don't seem to understand, it's the fact that writing secure code is always going to be more efficient than fixing an insecure application after the fact. Trust me when I say that we'll probably achieve world peace and solve global poverty before every programmer understands this. But that's enough of me being cheeky; let's get into the topic of this article: How to prevent XSS (Cross Site Scripting).
In a DevOps environment, it pays to be a security conscious developer and follow security best practices while writing code. One such proactive security measure you can take as a developer is to use Base64 to prevent XSS(Cross Site Scripting) attacks.
In this blog I want to discuss how to prevent XSS, and why only using Base64 is a bad idea. But before that, I should give you a short description of what XSS (Cross Site Script) and Base64 are.
According to OWASP, Cross-Site Scripting (XSS) attacks are a type of injection in which malicious scripts are injected into otherwise benign and trusted websites. XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application uses input from a user within the output it generates without validating or encoding it.
XSS attacks can generally be categorized into two ways: stored and reflected
In a reflected XSS attack, the attack is in the request itself (frequently the URL) and the vulnerability occurs when the server inserts the attack in the response verbatim or incorrectly escaped or sanitized. The victim triggers the attack by browsing to a malicious URL created by the attacker.
In a stored XSS attack, the attacker stores the attack in the application (e.g., in a snippet) and the victim triggers the attack by browsing to a page on the server that renders the attack, by not properly escaping or sanitizing the stored data.
Base64 is an encoding and decoding technique used to convert binary data to an American Standard for Information Interchange (ASCII) text format, and vice versa. It is used to transfer data over a medium that only supports ASCII formats, such as email messages on Multipurpose Internet Mail Extension (MIME) and Extensible Markup Language (XML) data.
During penetration testing of a client's web application, I noticed that some of the URL parameter values were encoded with base64. So I have decoded one of the parameter’s values(MotsClefs=QW1hem9u) and found a meaningful string(amazon).
The value of parameter ‘motoclef’ is base64 encoded
After this I tried sending the parameter value with base64 encoded javascript payload. It gave me a 'reflected XSS' like I expected. However, this is not a severe issue as no sensitive information was disclosed.
Payload :
b64 value: PHNjcmlwdD5hbGVydChkb2N1bWVudC5jb29raWUrJ2EnKTwvc2NyaXB0Pg==
The value of parameter ‘motoclef’ is replaced with base64 encoded javascript payload
But the same 'transparent base64 security' transformed into a severe vulnerability in other pages on the web application, namely the 'contact us' page in which the user can send queries and the 'Query status' page, where the user can check the current status of the query he/she has sent.
The value of parameter ‘Object’ is base64 encoded
I sent some test input queries from the 'contact us' page and noticed that the parameter's predefined values (FAQ dropdown menu) encoded with base64 was not properly sanitized or validated. All I had to do then was just intercept the request and replace the FAQ parameter value with base64 encoded javascript payload.
Payload :
b64 Value :PHNjcmlwdD5hbGVydCgnc3RvcmVkX3hzczEnKTs8L3NjcmlwdD4=
The value of parameter ‘Object’ is replaced with base64 encoded javascript payload
The request was sent successfully and executed in the 'Query Status' page. Unsurprisingly it was a Stored XSS and I don't have to say how bad a Stored XSS is.
The Payload Executed on ‘Query Status’ page was a stored XSS
Sanitizing user input is especially helpful on sites that allow HTML markup, to ensure data received can do no harm to users as well as your database by scrubbing the data clean of potentially harmful markup, changing unacceptable user input to an acceptable format.
Validating input is the process of ensuring an application is rendering the correct data and preventing malicious data from doing harm to the site, database, and users.
Escaping data means taking the data an application has received and ensuring it’s secure before rendering it for the end user. By escaping user input, key characters in the data received by a web page will be prevented from being interpreted in any malicious way.
Also, refer to the OWASP cheat sheet on how to prevent XSS for more info here:
Developers may try to make websites more secure by having a cryptic URL and parameters but, it doesn't protect web applications from attacks like XSS unless the user input is properly sanitized, validated and escaped.