Understanding the Cross-Site scripting (XSS) attacks

Cross-site scripting is a web vulnerability in which an attacker tries to inject and execute a malicious (external) script that is not part of the web application’s original source, which may compromise important data.

When this script is executed the attacker might steal sensitive information from the cookies, sessions, and tokens or any another source, and use it to access the user’s accounts, in the case of privileged users that could result in great harm.

Understanding the cross-site scripting (XSS) attacks is a crucial part when design the frontend system.

Understanding cross site scripting attack

How does XSS take place?

Cross-site scripting takes place when a hacker is able to inject and execute a malicious script and this usually happens because of human error and unnoticed bugs.

For example, a rookie developer injects a string directly into the DOM without sanitizing keeping the system vulnerable as a malicious script can be injected through it.

const str = "<script> //code that can steal your data </script>";
const ele = document.getElementById("#main");

// innerHTML directly injects the string in the DOM making it an HTML element exposing the vulnerability.
ele.innerHTML = str;

While the XSS attacks have many categories, they are majorly categorized into three parts by OWASP.

  • Stored XSS
  • Reflected XSS
  • DOM-based XSS

Stored Cross-site (XSS) scripting attack

In stored XSS the script is stored in the database and when accessed from the server, it is executed on the client side which could result in the compromisation.

To understand the Cross-site scripting attack we will take the example of a hosting website.

Assume you are chatting with the support on https://host-my-website.com

“Hello, I am not able to log into the Cpanel”

Where you are following up with customer support but you are not getting a response.

As you are a web developer, you use your instinct and try to highlight the words using the strong tag just out of curiosity.

“Hello, I am not able to log into the <strong>Cpanel</strong>” 

When this message is displayed on the screen you see that Cpanel has become bold and this catches the attention of the customer support and you get a reply instantly.

Now, this here is a vulnerability as we are passing HTML tags as a string but it is getting rendered as a DOM element, which means if we pass a script tag with a malicious code that too will be injected and executed.

Hello, I am not able to log into the <script>code to steal data</script> Cpanel” 

As this is a chat application and the string gets rendered on your as well as the customer support’s screen, the script can steal the data from the customer support who could be a privileged user and you can use that data to hack into the system.

As the chat is getting stored in the database and then it is retrieved on the request, the script is also getting stored, making it a stored XSS attack.

Based on the hierarchy of anyone who tries to access this chat, the script will be executed on their system and could result in compromising data.

If the server is using Nodejs then the malicious code could be executed on the server side as well.

Reflected cross-site (XSS) scripting attack

Reflected XSS, unlike stored does not require to be stored in a database, but depending on the rendering of the application, server-side or client-side the script is passed and executed on the DOM.

Taking the example of the same https://host-my-website.com, assume that you are now performing a search on the FAQ section to look for common issues.

When you type something in the search bar the URL is updated with the query and the same query is visible on the screen to highlight what you are searching for.

https://host-my-website.com?q=cpanel+access+revoke

Being a web developer, your instinct is fired again and you try to pass an HTML tag in the query parameter to check its effect.

https://host-my-website.com?q=cpanel+<strong>access</strong>+revoke

To your surprise, the word access in the search query is highlighted.

Knowing this you can do phishing along with the XSS where you make users click on the links that will inject a script that can help you to steal the user data.

Access your CPANEL
https://host-my-website.com?q=cpanel+<script>code to steal data</script>access+revoke

In the case of server-side rendering, the query is passed to the server and then it is returned and displayed on the screen, thus it is known as a reflected XSS attack.

DOM-Based cross-site (XSS) scripting attack

Dom-based XSS can be reflected or stored but it makes use of DOM’s API to execute the script.

For example, in the client-side rendering the routes are handled through JavaScript code.

In the routes, we also have hash-based routers and the routes can also handle the query params along with the hash.

Now, let us say we have this URL https://host-my-website.com#cpanel.

In the Ideal scenario, this will take us to the DOM element that has an id cpanel when the page loads.

But assuming a special case, where the hash component of the URL is accessed and is displayed on the screen.

Again, being a web developer, out of curiosity, you try to pass an HTML element https://host-my-website.com#<strong>cpanel</strong>.

The component is displayed in bold. Knowing this you can also pass a script here that will be injected and executed that could compromise your data.

The DOM-Based XSS attack requires a source (like hash) and a sink (like innerHTML) to work.

Preventing cross-site (XSS) attack

  • Sanitize the string – All the modern frameworks sanitize the string before rendering them to avoid the XSS attack. Wherever possible the strings are rendered as it is. For example, in React, the strings are rendered as it is, if you to render a string as HTML you will have to use dangerouslySetInnerHTML.
  • Use safe sink – If you are writing code in vanilla JavaScript, rather than appending the HTML using the innerHTML, try to create the DOM nodes and then append those like document.createTextNode(dangerVariable);, document.createElement(dangerVariable);.
  • HTML sanitization – Use libraries like DOMPurify to sanitize the HTML before injections.
  • Escape the HTML tags in the string – Case where the string has to be displayed as it is, the string can be encoded to escape them like & to "&amp;", < to &lt;, > to &gt;, " to &quot;, ' to &#x27;.
  • Setting the content security policy - Knowing your JavaScript code is important, you can set the right policy to make sure which script is safe that has to be executed, this can also prevent executing inline scripts.

Conclusion

While reading this it looks simple, but in reality, the hacker's attack won’t be straightforward, they use multiple techniques to keep their code unnoticed.

As a web developer, you can follow the best practices to keep your application as secure as possible.