Cross-Site Scripting (XSS): Attack Types & Prevention
Learn about XSS vulnerabilities including reflected, stored, and DOM-based XSS attacks, with hands-on detection and prevention techniques.
Prerequisites
- โข Basic understanding of HTML and JavaScript
- โข Familiarity with web application concepts
Understanding Cross-Site Scripting
Cross-Site Scripting (XSS) is a web security vulnerability that allows attackers to inject malicious scripts into web pages viewed by other users. It occurs when a web application includes untrusted data in its output without proper validation or encoding.
XSS attacks exploit the trust a user's browser places in the website. When a browser receives content from a website, it executes any scripts included in that content. If an attacker can inject their script into the page, it runs with the same privileges as legitimate scripts.
The impact of XSS can be severe: stealing session cookies to hijack user accounts, capturing keystrokes and form data, redirecting users to malicious websites, defacing web pages, spreading malware, and accessing any data the user can access through the application.
XSS consistently ranks in the OWASP Top 10 web vulnerabilities. Despite being well-understood, it remains prevalent because web applications have numerous input points and developers must correctly handle every single one to prevent XSS.
Types of XSS Attacks
Reflected XSS occurs when user input is immediately returned by the server without proper encoding. The malicious script is part of the request (typically in URL parameters) and reflected back in the response. The attacker distributes a crafted URL that, when clicked, executes the script.
Stored XSS (Persistent XSS) occurs when malicious input is saved by the server and later displayed to other users. Common locations include comments, forum posts, user profiles, and any user-generated content. Stored XSS is more dangerous because it affects every user who views the infected content.
DOM-based XSS occurs entirely in the client-side JavaScript code. The vulnerability exists in the page's JavaScript, which uses untrusted data (from the URL, document.referrer, or other DOM sources) to dynamically update the page content. The server never sees the malicious payload.
Each type requires different detection methods. Reflected XSS is found by testing URL parameters and form fields. Stored XSS requires monitoring where user input appears in the application. DOM-based XSS requires analyzing client-side JavaScript code for unsafe data handling.
Testing for XSS Vulnerabilities
Start with simple test payloads: inject '<script>alert(1)</script>' into input fields, URL parameters, and any point where user data is reflected in the page. If an alert box appears, the application is vulnerable to XSS.
When basic payloads are filtered, try bypass techniques: encode characters using HTML entities, URL encoding, or Unicode. Use event handlers ('onerror', 'onload', 'onfocus') instead of script tags: '<img src=x onerror=alert(1)>'. Break out of HTML attribute contexts.
Automated tools help identify XSS efficiently. Burp Suite's scanner tests parameters systematically, OWASP ZAP provides both automated scanning and manual testing tools, and browser developer tools help analyze how input is processed and rendered in the DOM.
Test with context-appropriate payloads. XSS in an HTML body requires different payloads than XSS in a JavaScript string, an HTML attribute, a URL parameter, or a CSS context. Understanding the injection context is crucial for crafting successful payloads.
Preventing XSS Attacks
Output encoding is the primary defense. Encode all user-controlled data based on its output context: HTML entity encoding for HTML body content, JavaScript encoding for JavaScript contexts, URL encoding for URL parameters, and CSS encoding for style contexts.
Input validation provides a secondary defense layer. Validate all user input against strict whitelists โ expected formats, lengths, and character sets. Reject or sanitize input that does not conform to expectations. Never rely on input validation alone without output encoding.
Content Security Policy (CSP) headers restrict which scripts the browser is allowed to execute. A properly configured CSP can prevent inline script execution, restrict script sources to trusted domains, and block dangerous functions like eval(). CSP is a powerful defense-in-depth measure.
Use security-focused frameworks and libraries that handle encoding automatically. Modern frameworks like React automatically encode output by default, significantly reducing XSS risk. However, functions like dangerouslySetInnerHTML bypass this protection and must be used with extreme caution.
Ready to Go Deeper?
This tutorial covers the basics. Join our instructor-led program for hands-on projects, certification prep, and placement assistance.