XSS Cheat Sheet

Cross-site scripting (XSS) is one of the most common and dangerous vulnerabilities found in web applications.

XSS attacks occur when an attacker injects malicious scripts into web pages that are viewed by other users. This allows the attacker to steal sensitive information, such as session cookies, credentials, and personal data, or even to perform actions on behalf of the user without their consent. Given the increasing amount of personal and financial data stored online, preventing XSS attacks is critical for safeguarding both users and web applications.

The concept of XSS has been around for over two decades, originating in the early 2000s when security experts began noticing that improperly sanitized input fields on websites were being exploited by attackers to inject malicious JavaScript. Since then, XSS vulnerabilities have remained a major concern for developers, as this type of attack can target virtually any website, especially those that rely on user-generated content.

Types of XSS Attacks

Over time, various types of XSS attacks have been identified, each with its own method of execution and impact. As a result, understanding how to prevent XSS vulnerabilities and mitigate the potential risks can require different strategies.

The types you might encounter include:

  • Stored XSS (Persistent XSS): Malicious script is injected into a web application’s database or server and stored permanently. When other users load the page, the script is executed from the server, affecting all users who visit that page. Can impact multiple users because the malicious script is served to anyone who accesses the page.
  • Reflected XSS (Non-Persistent XSS): The malicious script is reflected off a web server, usually through a URL or HTTP request. It’s executed immediately when a user clicks a link or submits a request, without being stored on the server. Typically affects only the user who clicks the malicious link, but it can be exploited if the attacker tricks users into clicking.
  • DOM-based XSS: The vulnerability exists in the client-side code (JavaScript) rather than in the server-side code. The attacker manipulates the Document Object Model (DOM) in the browser to execute malicious scripts. The malicious script is executed on the client side without any interaction with the server.
  • Self-XSS: The attacker tricks the victim into running a script by pasting malicious code into the browser’s developer tools or address bar. Often, the victim is led to believe they are doing something benign. It requires user interaction, but the victim is tricked into executing the code voluntarily.
  • Mutated XSS: An attacker injects a payload that is initially sanitized but later mutated by client-side JavaScript, causing the payload to execute. It can bypass input filtering and execute code on the client side after being altered.
  • Advanced Persistent XSS: A highly advanced form where the injected script can bypass filtering mechanisms by using sophisticated payloads and encoding techniques. It remains persistent in the system over time, targeting the same or new users.

By understanding these different types of XSS vulnerabilities, developers and security professionals can better defend against them, ensuring their web applications are secured from malicious attacks.

Keep Aware of XSS

This XSS cheat sheet is a valuable resource for anyone involved in web security, providing essential guidelines and techniques to prevent XSS attacks. It covers various attack vectors, common methods used by attackers, and effective defensive strategies.

The audience for the Cheat Sheet includes developers, penetration testers, and security researchers. All of these professionals need to ensure that web applications remain secure against one of the most persistent and harmful threats in cybersecurity.

Identify XSS: Manual Code Reviews and Testing

Code review has the primary objective of uncovering security vulnerabilities within applications and pinpointing their precise origins. This process entails a thorough examination of the application’s source code to ensure it possesses the necessary self-defensive capabilities for its specific environment. OWASP emphasizes the critical nature of code review by stating that the absence of such scrutiny virtually guarantees the existence of issues in the application. While tools can assist in this endeavor, they cannot grasp the context, making human verification indispensable. This is where manual security code review assumes a crucial role.

If manual code review is done correctly, a penetration test afterward using automated tools should discover little or no vulnerabilities. Interestingly, OWASP provides a detailed guide on manually reviewing code for XSS vulnerabilities, including a complete manual testing guide for reflected XSS, stored XSS, and DOM-based XSS vulnerabilities for your reference. The following manual processes can be used to identify common XSS vulnerabilities:

  • Identify code that outputs user input Failure to properly sanitize user input in code exposes it to the risk of Cross-Site Scripting (XSS) vulnerabilities. To ascertain whether your code is placed within an attribute, you can press Ctrl + U to inspect the page output source in your browser. If it is, you can test the output by injecting the following code: “onmouseover=alert(‘hello’);”.
  • For testing purposes, you can use this script: <script>alert(document.cookie);</script>. However, if the code you are reviewing filters out < and > characters, you should try the following script instead: &{alert(‘hello’);}”. This allows you to assess whether the code effectively mitigates potential XSS threats.
  • Check that output is encoded Ensure that HTML output, which may include various forms of input, is properly encoded using HtmlEncode. Similarly, make sure that URL strings are encoded using Uuencode. Input data can originate from diverse sources, such as query strings, form fields, cookies, HTTP headers, and data read from shared databases used by other applications. Failing to apply these encodings puts your application at risk of XSS vulnerability. Implementing proper encoding measures not only enhances security but also prevents the browser from treating the HTML content as an executable script, thus mitigating potential XSS threats.
  • Identify code that handles URLs Code that governs URLs can risk XSS and other vulnerabilities. Review your code and systems as follows:
    • Check that your web server is updated. If your web server is not up-to-date with the latest security patches, it could be vulnerable to directory traversal attacks.
    • If your code filters for “/”, an attacker can easily bypass the filter by using URL encoding (percent-encoding) for the same character. For example, the percent-encoding for “/” is “%c0f%af”, which could be used to bypass the filter as shown in the following URL: http://www.abc.com/..%c0f%af../winnt.
    • If your code processes query string input, check that it constrains the input data and performs bounds checks. Also, check that the code is not vulnerable if an attacker injects a massive amount of data through a query string parameter like the URL shown here: http://www.abc.com/test.aspx?var=InjectHugeAmountOfDataHere.
  • Unit test your codes Unit testing is a software testing method by which individual units of source code are tested to determine whether they are fit for use. Unit testing aims to isolate each part of the program and show that the individual components are correct. Use unit testing to make sure that a particular bit of data is correctly escaped. Unit testing helps to identify XSS and other flaws early in the development cycle. If possible, unit test every place where user-supplied data is displayed. After you find and fix an XSS bug in your code, consider adding a regression test for it.
  • Perform these basic tests on your application Create a test user profile and use that profile to interact with your application. Insert strings that contain HTML and JavaScript meta characters such as  >’>”><img src=x onerror=alert(0)> into all application inputs, such as forms, URL parameters, hidden fields, or cookie values.

If your application doesn’t correctly escape this string, you will see an alert and know that something isn’t right. Wherever your application handles user-supplied URLs, enter the following javascript code: alert(0) or data:text/html,<script>alert(0)</script>. All of these can help identify stored XSS bugs.

Identify XSS: Automated Application Testing

Detecting XSS vulnerabilities in web applications can be achieved through standard security testing techniques and tools. Notable methods include:

  • Static Application Security Testing (SAST) SAST secures applications by reviewing their source code to identify potential vulnerabilities or insecure practices. Since it operates independently of the application’s runtime, waiting for deployment is unnecessary, allowing for faster and more cost-effective vulnerability detection. Employing a white-box approach, SAST scans the source code and components to pinpoint security flaws.
  • Dynamic Application Security Testing (DAST) DAST tools interact with applications via the front end to uncover potential security vulnerabilities. Lacking access to source codes, they rely on black-box testing strategies, performing attacks during code execution. Dynamic analysis utilizes techniques like fuzzing, which tests the application with random, malformed data to uncover XSS flaws.
  • Interactive Application Security Testing (IAST) IAST combines the strengths of SAST and DAST. It examines code for XSS and other security vulnerabilities while the application is running, interacting with its functionality.

Leveraging these techniques enables swift testing and detection of XSS vulnerabilities in web applications. Web vulnerability scanners, such as Netsparker, Acunetix, Veracode, and Checkmarx, are powerful tools that automatically crawl the entire website or application, checking for XSS and other security flaws. While these scanners may not be tailor-made for specific applications, they efficiently detect obvious vulnerabilities and implement many of the testing techniques discussed earlier. Furthermore, they allow for vulnerability scanning, report generation, and even attempt automatic fixes.

Prevent XSS

First and foremost, it is imperative to acknowledge that no solution can be guaranteed foolproof, given the swift evolution of technology and the ever-advancing sophistication of attacks. By grasping the fundamentals, you can prepare to counter future attack techniques effectively. The following are some recommendations to prevent or minimize XSS vulnerabilities:

  • Use Secure Coding Practices To secure your web application and prevent XSS attacks, follow sound coding practices. Be cautious when using user input to generate output for other users. Adhere to the golden rules of user input: treat all data as potentially harmful until verified, and filter data at the boundary between untrusted and trusted domains. By implementing security coding practices recommended by OWASP, you can significantly decrease common vulnerabilities, including XSS.
  • Filter User Inputs To prevent XSS vulnerabilities, ensure all external data (user input) passes through a filter that removes hazardous tags and attributes like <script>, <applet>, <html>, <frame>, <img>, <embed>, and JavaScript commands. You can either develop your own filter mechanisms or utilize reliable, pre-existing libraries. However, be aware that experienced attackers might attempt to bypass simple filters using techniques like hex encoding, Unicode character variations, line breaks, and null characters. As a result, user input filtering alone may not suffice against advanced XSS attacks. Consult the OWASP filter evasion cheat sheet for guidance on guarding against such exploits.
  • Use Escaping Techniques A common technique for preventing XSS vulnerabilities is “escaping”. When you use escaping techniques, you effectively tell the web browser that the data you are sending should be treated as data and not be interpreted as a control character or code. Thus, if an attacker manages to inject an XSS script on your page, the malicious code will not be executed if it is properly escaped. However, to guarantee the security of your web applications, you must master the use of escaping techniques for HTML, JavaScript, CSS, and sometimes XML data. This is because these languages require different forms of escaping for each context.

In HTML, you can escape dangerous characters by using HTML entities such as &# sequence followed by its character code. For example, ‘&lt;’ and ‘&gt;’ are the HTML encoding for the ‘<‘ and ‘>’ characters, respectively. If you include: <script>alert(‘testing’)</script> in the HTML of a page, the script will execute. But if you include the character codes in the HTML of a page as shown here: &lt;script&gt;alert(‘testing’)&lt;/script&gt;

It will print out the text “<script>alert(‘testing’)</script>”, but it will not execute the script. By escaping the <script> tags, we prevented the script from executing. Use HTML escaping when untrusted data is inserted between HTML opening and closing tags.

Similarly, use JavaScript or CSS escaping when untrusted data is inserted inside one of your scripts or CSS styles, as the case may be. This includes event handlers such as on mouseover and upload and certain HTML attributes such as style. For example:

<script>alert('If this data is untrusted, it must be JavaScript-escaped.')</script>

<body onload="If this data is untrusted, it must be JavaScript-escaped.">

You can do all the escaping by writing the code yourself. However, writing your code for escaping user input and adequately and consistently applying it is extremely difficult. Therefore, we recommend using existing libraries such as OWASP ESAPI, Microsoft AntiXSS (best suited for Microsoft environment), or web development frameworks or templates that provide context-aware auto-escaping. If you use templates to generate HTML within JavaScript, Closure Templates and Angular provide built-in escaping capabilities.

Other things you can do to prevent XSS vulnerability or minimize the chances of XSS attacks include:

  • Learning the best practices for your server-side and client-side technologies, such as using HTML sanitizer or configuring your browser to use a proxy that intercepts and scans traffic such as Burp Proxy and ratproxy to help identify problems.
  • Using a web template system or a web development framework with context-aware auto-escaping.
  • Manually escaping user input (if template system with context-aware auto-escaping is not feasible)
  • Understanding common browser behaviors that lead to XSS.

Summary 

Detecting and mitigating XSS vulnerabilities in web applications is not a simple task with a one-size-fits-all solution. It requires a balanced approach, combining human effort through manual code reviews and technology support via automated tools like vulnerability scanners. On one end of the spectrum, a developer, and an application security reviewer may manually inspect codes using a text editor. On the other end, an expert security team may utilize advanced Static Application Security Testing (SAST) tools.

Automated tools excel at assessing vast amounts of code and identifying potential issues. However, human verification is crucial to determine if these results are exploitable and assess the risk to the organization. Automated tools have limitations and cannot cover all potential vulnerabilities, leaving significant blind spots that human reviewers must address. Emphasizing a combination of manual code reviews and automated testing is essential, as no testing methodology guarantees absolute security. This approach will significantly reduce the likelihood of an XSS vulnerability within your application.