XSS Cheat Sheet

Cross-site scripting (XSS) remains one of the most widely exploited security flaws affecting modern web applications.

It occurs when an attacker injects malicious scripts into web pages that are then executed in the browsers of other users. This can allow attackers to steal sensitive information such as session cookies, credentials, and personal data, or perform actions on behalf of users without their consent. With increasing amounts of personal and financial data stored online, preventing XSS is essential for protecting both users and applications.

The concept of XSS has existed for over two decades, emerging in the early 2000s when security researchers identified that improperly sanitised input on websites could be exploited to inject malicious JavaScript. Since then, XSS has remained a persistent and widely exploited vulnerability, particularly in applications that rely heavily on user-generated content.

Types of XSS Attacks

  • Stored XSS (Persistent XSS):
    Malicious scripts are injected into a web application and stored on the server (often in a database). When users access the affected page, the script is delivered and executed in their browser. This can impact multiple users who view the compromised content.
  • Reflected XSS (Non-Persistent XSS):
    The malicious script is embedded in a request (such as a URL) and reflected back by the server in its response. It executes immediately when a user clicks a crafted link or submits a request, without being stored. This typically affects only the user who interacts with the payload.
  • DOM-based XSS:
    The vulnerability exists in client-side code rather than the server. The attacker manipulates the Document Object Model (DOM) in the user’s browser to execute malicious scripts. In this case, the payload is executed entirely on the client side.
  • Self-XSS:
    The attacker convinces a user to execute malicious code themselves, often by pasting it into browser developer tools or the address bar. Although it relies on user action, the execution is still harmful and can lead to account compromise.
  • Mutated XSS:
    A payload is initially sanitised but later altered (“mutated”) by client-side JavaScript in a way that allows it to execute. This can bypass certain input filters and validation mechanisms.
  • Advanced Persistent XSS:
    A more sophisticated form of XSS where attackers use encoding techniques and advanced payloads to bypass security controls. The injected script remains in the system and can continue to affect users over time.

By understanding these different types of XSS vulnerabilities, developers and security professionals can better identify risks and implement appropriate protections to secure web applications against malicious attacks.

Stay Aware of XSS

This XSS cheat sheet is a practical reference for web security professionals, offering key guidance on how to prevent and mitigate cross-site scripting attacks. It outlines common attack vectors, techniques used by attackers, and effective defensive measures.

The cheat sheet is designed for developers, penetration testers, and security researchers who are responsible for securing web applications. These roles require a clear understanding of XSS risks in order to protect systems against one of the most persistent 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.