Introduction to Cross-Site Scripting
Cross-Site Scripting (XSS) is a security vulnerability that primarily stems from inadequate input validation and output encoding within web applications. For bug bounty hunters, XSS is one of the most lucrative and frequently reported vulnerabilities, often fetching significant rewards due as it is easy to find and can have a massive impact.
The sheer prevalence [widespread existence] of XSS is evidenced by its consistent inclusion in the OWASP Top 10 list of the most critical security risks to web applications over the last decade.
This type of vulnerability exists because developers fail to implement strict validation controls across all data entry points in an application. While XSS is traditionally found in HTML forms where users interact directly with the application, vulnerable inputs can also originate from:
- Interactions between other applications.
- Environmental variables.
- External data sources.
A Client-Side Focus
One of the most curious and defining characteristics of XSS is its focus on the client side. Most other common web vulnerabilities target the application itself, exploiting the backend [the server-side code and database] to cause a failure.
In contrast, XSS attacks inject malicious code—usually JavaScript—into a web page viewed by another user. The attack is successful when the victim’s web browser executes the malicious script, meaning these attacks require user interaction to be successful.
Understanding the Core XSS Types
The primary and most fundamental types of XSS attacks are categorized based on how the malicious script reaches and is executed by the victim’s browser.
The Attack Taxonomy
| Primary Types | Community-Specific Variants |
| Reflected XSS | Blind XSS |
| Stored XSS | Flash-based XSS |
| DOM-based XSS | Self XSS |
1. Reflected Cross-Site Scripting
Reflected XSS, sometimes referred to as First-Order XSS, is a non-persistent vulnerability. It is executed at the exact moment a user clicks a malicious link or submits a specially crafted [skillfully made, often deceptive] form.
The malicious script is immediately “reflected” off a web application server and delivered to the user. It most commonly affects GET requests, where the input is sent via the URL parameters.
Impact Explained Through an Example
Imagine a scenario where a user, like your grandmother, receives a phishing email that appears to be from her bank. The email offers a promotion and contains a link. The user, checking the address bar, confirms the bank’s valid domain name, seemingly following good security practices.
However, the link itself contains a malicious payload [the harmful code being delivered], such as:
www.bankforoldpeople.com/access?account='>When the user clicks the link, the bank’s web server takes the unvalidated input from the account parameter and includes it directly in the resulting page displayed to the user. The browser, seeing the unclosed tag ('>) followed by the tag, executes the attacker’s code. The result could be:
- The theft of the user’s session cookies.
- Redirection to a malicious login page to steal credentials.
- The automatic execution of an unauthorized transaction.
2. Stored Cross-Site Scripting
Stored XSS, also known as Persistent XSS or Second-Order XSS, is significantly more dangerous because the malicious attack string is permanently stored in a data storage component, typically a database.
The attack requires two distinct steps:
- The attacker injects a malicious string into a form (e.g., a comment section, a user profile field, or a message board).
- The application accesses this information and shows the malicious string to any user who views that stored data, causing the script to execute repeatedly in their web browser.
A Real-World Scenario
In a reported incident, a security researcher targeted an application where developers had bypassed the security features of the Laravel framework, choosing to write input-handling code using PHP directly. This lapse created a vulnerability.
The researcher used a tool like Burp Suite’s Intruder to insert a malicious string into customer profile fields, which were stored in a MySQL database. The application’s purpose was to allow customers to view revenue generated by marketing campaigns.
The failure occurred when customers accessed the application:
- The application searched the database for the profile information.
- It read the malicious string from the stored data.
- It displayed a series of alert pop-ups to the users for each affected field, rendering the application unusable due to the overwhelming quantity of alerts.
This demonstrates Stored XSS: the malicious payload was persisted in the database and then served to many unsuspecting users.
3. DOM-Based Cross-Site Scripting
In Reflected and Stored XSS, a data source interacts with the application server to insert a value. DOM-based XSS is different because the server is often not involved in the actual attack execution.
In this type of attack, the vulnerability lies entirely within the client-side script itself.
Understanding the Document Object Model (DOM)
To grasp DOM-based XSS, an understanding of the Document Object Model (DOM) is necessary.
The DOM is an interface for HTML and XML documents that allows scripts to access and modify the structure, style, and content of a document. It structures a web page into a series of nodes and objects, connecting the document with programming languages, most notably JavaScript.
The Client-Side Vulnerability
In a DOM-based XSS attack:
- The user sends a crafted URL containing the malicious code (e.g., in a URL fragment or query parameter).
- The server processes the request, but does not include the injection in the response body.
- Instead, a client-side script in the user’s browser processes the response and pulls data from the DOM (e.g., from the URL’s hash or query string) without proper sanitization.
- The script then executes the malicious injection, which was never sent from or processed by the server.
For instance, consider a script that reads a message parameter from the URL and writes it directly to the page:
script>
// Get the part of the URL containing the parameters
var message = document.location.search.substring(1);
// Write the unvalidated message into the page's HTML
document.getElementById("output").innerHTML = message;
script>If the value for message is a malicious string, the script will show the attack to the user in the browser. The malicious string never originated from the server’s code; it was entirely processed on the client side using a property contained within the DOM.
Other Important XSS Variations
While the three types above form the basis of all XSS attacks, the bug bounty community uses additional terms to describe specific contexts or exploitation methods that are crucial for reporting.
Blind XSS
Blind XSS occurs when an application reads data from a data source that is shared with one or more other applications. This is essentially a form of Stored XSS, but the attacker is “blind” to the direct result of their payload because they cannot see the victim’s application.
For example:
- A public-facing application accepts customer feedback, which is stored in a database.
- An internal administrative application reads that same database to display the feedback to an employee.
- If an attacker injects a malicious payload into the public feedback form, the script will be executed when an internal administrator (the “blind” victim) views the feedback in their secure panel.
The payload is stored via one application but executed via another, often granting the attacker access to a high-privilege account.
Flash-Based XSS
Years ago, a technology called Flash (developed by Adobe, now deprecated and largely obsolete) was widely used for creating dynamic websites and interactive content. Because Flash allowed graphic designers and inexperienced users to create forms and routines without deep programming knowledge, many Flash-based applications suffered from a lack of input validation.
An XSS vulnerability found in these applications was historically referred to as Flash-based XSS. Today, these are simply considered standard XSS vulnerabilities that were present in applications built on the Flash platform.
Self XSS
Self XSS describes a scenario where a user is tricked into auto-executing an XSS attack on their own web browser. The vulnerability is not in the injection point but in the potential for social engineering.
The victim copies and pastes a malicious script (or payload) into their browser’s console, causing the XSS to execute on their own session. Although the user is “hacking themselves,” the goal is to steal sensitive information like cookies or session tokens which are then forwarded to the attacker.
While once considered low-risk, security researchers have demonstrated that this can be successfully exploited through sophisticated social engineering vectors. For a deeper dive into this, the presentation Self XSS we’re not so different you and I is available for review: Self XSS we’re not so different you and I.
Detecting Cross-Site Scripting (XSS) Bugs
Detecting XSS vulnerabilities fundamentally involves testing every user-controlled input to determine how the web application processes and displays the data in its response. The primary tool used for this process is an HTTP Proxy, such as Burp Suite or OWASP ZAP.
The Core Detection Strategy
The detection process is systematic and focused on analyzing the application’s response to special input characters.
1. Using an HTTP Proxy
The first step is to route all application traffic through an HTTP Proxy. This allows a security professional to intercept, analyze, and modify every HTTP request made by the application being assessed.
The goal is to analyze each input field by field by modifying the content with basic testing strings.
2. The Basic XSS Test String
The most basic and essential test string used to check for XSS is often.
script>alert('XSS')script>This string attempts to execute a simple JavaScript function (alert()) that, if successful, will display a pop-up box, confirming the vulnerability.
3. Tip: Identify Reflected Inputs
A crucial tip for finding input validation vulnerabilities is to note that any input taken from the user and immediately shown back to them in the application’s response is susceptible to a vulnerability.
For example, when a user submits a comment, the application might respond with:
- “Thank you for your comment, [Username]!”
The value of the [Username] parameter is a direct reflection of the user’s input, making it a high-priority target for testing.
Step-by-Step Character Analysis
To confirm an XSS vulnerability, a hacker or tester must understand how the application handles special characters that are fundamental to HTML and JavaScript syntax.
Step 1: Inputting Special Characters
Insert a string of special characters that are commonly used in HTML and JavaScript code into the target input field. These characters are critical because an application must properly encode [convert a character into a different format] them to prevent script execution.
A common test string includes:
> ' " / ;These characters are used to:
andOpen and close HTML tags.>:'and": Define string boundaries and attribute values./: Close tags and define paths.;: End JavaScript statements.
Step 2: Examining the Application’s Response
After submitting the special characters, immediately examine the HTML source code of the application’s response. This is the most critical step.
A secure application should encode or sanitize these characters, preventing them from being interpreted as code. For example, a properly secured application might convert the string to:
| Original Character | HTML Entity Encoding (Secure) |
(Less-than sign) | < |
> (Greater-than sign) | > |
" (Double quote) | " |
Step 3: Verifying Unsafe Character Handling
If, upon checking the HTML source code of the response, you find that the application is showing the special characters just as they are (e.g., is reflected as and not <), this is a strong indicator of a vulnerability.
When the browser parses the unencoded characters, it interprets them as executable HTML or JavaScript, meaning a successful XSS payload can be injected.
Evading Security Measures: Bypassing XSS Input Validation Controls
While many modern web applications implement security measures like input validation, sanitization, and output encoding to prevent Cross-Site Scripting (XSS) injections, these controls can often be circumvented [skillfully avoided or overcome] by a determined attacker or bug bounty hunter. Bypassing these filters typically involves creative use of encoding, character modification, and dynamic string construction.
Common Testing Strings and Wordlists
To automate the detection process, security researchers use comprehensive lists of known malicious strings, or payloads. These strings are designed not only to trigger a simple XSS alert but also to test for vulnerabilities in SQL Injection, and other forms of code injection.
A Library of Payloads
Here is a list of common strings you can use to detect various injection vulnerabilities:
| Category | Payload Examples | Purpose/Target |
| Basic XSS/HTML Breakout | ' , > , '> , '>"> | Test for closing quotes/tags to insert code. |
| SQL Injection (SQLi) | '1 or 1==1-- , ' or 1==1 | Test for database authentication bypass. |
| XSS Payloads | '> | Basic script execution test. |
| Alternative XSS Tags | "> | Uses the tag and its onerror attribute to execute code. |
| iFrame XSS | "> | Uses an to execute JavaScript. |
| URL Redirection | article.php?title= | Test for meta tag injection to force a page refresh or redirect. |
| SQLi Time Delay | SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/ | Tests for SQL injection by inducing a time delay on the server. |
| Advanced XSS/JS | ';alert(String.fromCharCode(88,83,83))// | Uses character codes (88, 83, 83 = XSS) to avoid filtering of the word alert. |
| Complex Tag Breakout | `”> | >prompt(1)` |
Workflow Recommendation
It is highly recommended to save these strings in a TXT file and use them as a wordlist with an automated tool like Burp Suite’s Intruder. This allows a tester to launch the strings against all fields in an HTTP request simultaneously, drastically speeding up the detection process. The tester can then use the proxy’s Search function to look for any reflected instance of the injected string in the HTTP responses.
Filter Evasion Techniques
Applications often employ blacklists (lists of forbidden words like script or alert) or whitelists (lists of allowed words) to filter user input. Attackers use several creative techniques to bypass these checks.
1. Bypassing Filters Using Encoding
Encoding converts characters into a different format that is still readable by the browser but may be overlooked by a simple filter.
-
HTML Entity Encoding: A simple example is encoding the
and>characters to bypass a simple blacklist:can be encoded as:
<script>alert(1)</script>If the filter only looks for the literal string , the encoded string may pass through, and the browser will automatically decode it for rendering, executing the script.
-
Other Encoding Methods: Other techniques include using URL encoding (e.g.,
%20for a space), Base64, or hexadecimal encoding.
2. Bypassing Filters Using Tag Modifiers
This technique involves slightly modifying the structure of the payload to confuse simple string-matching filters while remaining valid code for the browser.
-
Case Variation: Modifying the casing of the tag name is effective against non-case-sensitive filters:
can be changed to:
Browsers interpret these lines in the same way, but some filters might only be looking for the all-lowercase version.
-
Alternative Spacing and Characters: Modifying the spaces within a tag using unusual, yet valid, characters can bypass filters:
can be changed by substituting the space with URL-encoded special characters:
-
Bracket Modification: Using different types of accepted brackets or partial encoding:
«img onerror=alert(1) src=a» %253cimg%20onerror=alert(1)%20src=a%253e ```
3. Bypassing Filters Using Dynamic Constructed Strings
For more advanced filters, the malicious string itself is dynamically constructed at runtime using JavaScript functions. This prevents the filter from seeing the forbidden keywords in the initial input.
-
String Concatenation (Joining):
The filter won’t see
alertas a single, forbidden word. Theeval()function executes the concatenated string. -
Character Code Conversion: Using ASCII or Unicode character codes to represent the payload:
The numbers (97, 108, 101, 114, 116, 40, 49, 41) decode to the string
alert(1). -
Base64 Decoding: The
atob()function decodes a Base64 string:
Workflow of an XSS Attack
An XSS attack requires three key components: a web application, a victim, and an attacker. In a common scenario, the attacker’s main objective is session hijacking—impersonating the victim by stealing their session cookie.
The overall steps for a Stored XSS attack are as follows:
- Injection: The attacker initially injects malicious JavaScript into a field that is stored in the application’s backend (e.g., a comment or profile field).
- Request: The victim sends an HTTP request to the web page where the malicious JavaScript is stored.
- Display: The application’s server retrieves the stored malicious data. The victim’s browser receives the page, including the attacker’s payload as part of the HTML content.
- Execution: The victim’s browser executes the malicious JavaScript, which often includes a command (like
document.cookie) to steal the session cookies and send them to a server controlled by the attacker. - Hijacking: The attacker then uses these stolen cookies to pose as the victim, resulting in session hijacking.
HackerOne Stored XSS Vulnerability
This real-world report highlights how a seemingly simple vulnerability can lead to a high-impact security breach.
Report Summary
| Field | Detail |
|---|---|
| Title | Vulnerability with the way \ escaped characters in http://danlec.com style links are rendered |
| Reported by | danelc |
| Bounty Rewarded | $5,000 |
| Application | HackerOne.com (a bug bounty coordination platform) |
The Vulnerability
The XSS vulnerability was found in the parsing of link syntax within the HackerOne reporting form’s description field. This was a Stored XSS bug.
The issue arose because the application’s parser was incorrectly handling the backslash (\) escaped characters used in links. If a user pasted a text string such as:
test\>
The application would incorrectly process the escaped characters, rendering the string as:
http://test
This error allowed an attacker to inject arbitrary code, as the parser misinterpreted the escaped characters as literal HTML tags.
Exploitation Payloads
The attacker demonstrated the impact using various payloads:
-
Executing Malicious JavaScript: Stealing cookies or session information.
Payload Submitted Payload Rendered/Executed >http:// -
Embedding Unauthorized Images: Bypassing the platform’s Content Security Policy (CSP) to post images.
Payload Submitted Payload Rendered/Executed http:// -
Redirecting Users: Bypassing the platform’s redirect middleware.
Payload Submitted Payload Rendered/Executed Redirect\ bypassed\>http://Redirect bypassed
Slack Stored XSS via Markdown Editor
This report details a high-impact Stored XSS vulnerability in a critical enterprise collaboration tool.
| Field | Detail |
| Title | Stored XSS on team.slack.com using the new Markdown editor of posts inside the editing mode and using JavaScript URIs. |
| Reported by | fransrosen |
| Bounty Rewarded | $1,000 |
| Application | Slack.com (Online team collaboration platform) |
Vulnerability Description
The vulnerability was identified within Slack’s real-time document-editing feature for text posts. This feature allows multiple team members to collaborate on a document simultaneously.
- When a document is uploaded, it is stored in the
/files/directory of the Slack domain. - The XSS was triggered in the editing mode when a user modified a post that contained a link with a JavaScript URI payload.
- The core of the vulnerability relied on catching modifications from the WebSocket and injecting the malicious payload there.
The Exploit Mechanism
The attacker used the following test URL, which pointed to the file:
https://marqueexss.slack.com/files/marqueexss/F0283AA4K
The goal was to embed a malicious link behind a piece of text, such as:
This payload listed as javascript:alert(“XSS”) is the vulnerable code with a link embedded behind it.
Since direct injection of the javascript:alert("XSS") payload into the text was filtered, the attacker bypassed the control by injecting the payload into a WebSocket notification. When multiple users edit a document, their changes are communicated via WebSocket messages.
The attacker executed the following steps:
- Delete an existing link behind the target text.
- Press Ctrl + Z to undo the deletion.
- Put the link back using the editor.
- Capture the WebSocket request that communicated this change.
- Modify the request to insert the malicious JavaScript URI payload (
JavaScript:alert(\"XSS\"%29) into thelinksparameter of the WebSocket JSON payload.
This successfully stored the payload within the document’s link metadata. When other team members viewed or edited the document, the malicious link would execute the JavaScript, compromising multiple users.
Key Learning from this Report
- Test Non-Traditional Inputs: An XSS vulnerability does not have to be in a parameter that is visible in the original HTTP request. Bug hunters must test all requests, including those generated by WebSockets or internal application logic.
- Turning Self-XSS into Stored XSS: The reporter initially leveraged a client-side action (undo/redo) but went to great lengths to document and prove that the vulnerability resulted in a Stored XSS that could affect other users, significantly increasing its impact and bounty value.
Trello DOM-based XSS via Wistia Integration
This report is an excellent example of finding a vulnerability not in the target application, but in a third-party service that the application relies on.
| Field | Detail |
| Title | DOM-based XSS via Wistia embedding. |
| Reported by | reacter08 |
| Bounty Rewarded | $1,152 |
| Application | Trello.com (Web-based project management) |
Vulnerability Description
Trello, which utilizes boards and cards for project management, integrates with Wistia for embedding videos. The XSS vulnerability was found in how Trello utilized Wistia’s video embedding mechanism, specifically in a vulnerable Wistia JavaScript library (fast.wistia.net/assets/external/E-v1.js).
The attack was a DOM-based XSS because the injection was executed by the user’s browser (client-side) using URL parameters, not by the Trello server.
The Exploit Mechanism
The vulnerability was triggered by combining two specific URL parameters used in the Wistia embedding process:
wchannelParameter: Used to load external JavaScript from the vulnerable Wistia libraries.callbackParameter: Used to control the output of the script being loaded.
The attacker crafted a URL that chained these two parameters together, forcing the Wistia script to include and execute a malicious payload in its output.
A typical exploitation URL looked like this:
https://fast.wistia.com/embed/medias/[video_id].json?callback=[controlled output]
The full malicious URL payload, when executed on Trello’s guide subdomain, demonstrated the vulnerability:
https://trello.com/guide/customize.html?wchannel=../../../../embed/medias/1yqpy8ics4.json%3fcallback%3dalert(1)%253bvar%20x%3d%27%253bx(//%23
This payload resulted in an XSS alert box being displayed on various Trello subdomains (e.g., trello.com/guide, blog.trello.com, help.trello.com), demonstrating the wide reach of the reflected attack.
The vulnerability was significant because it functioned as a reflected XSS and could potentially compromise Trello and all other websites using the vulnerable Wistia video integration, such as Olark and WordPress.
Key Learning from this Report
Creative Payload Crafting: Success depended on crafting a payload that utilized the third-party parameters (wchannel and callback) to achieve code execution in the target environment (Trello).
Test Third-Party Integrations: The most important lesson is that bug bounty hunters must look beyond the target application’s code and test all third-party libraries, widgets, and integrations (e.g., video players, comment sections, analytics scripts). A vulnerability in a third-party script can easily become an exploitable vulnerability on the host domain.
Shopify XSS: SVG Whitelist Bypass
This report demonstrates how a seemingly secure file upload feature can be bypassed using cleverly crafted XML within a Scalable Vector Graphics (SVG) file, leading to a high-impact Stored XSS that spans multiple domains.
| Field | Detail |
| Title | XSS on $shop$.myshopify.com/admin/ and partners.shopify.com via a whitelist bypass in the SVG icon for sales channel applications. |
| Reported by | Luke Young |
| Bounty Rewarded | $5,000 |
| Application | Shopify (https://*.shopify.com) |
Vulnerability Description
Shopify allows developers to create applications for their platform, including sales channel extensions. Developers can upload icon images for these apps in formats like JPG, GIF, and SVG (Scalable Vector Graphics).
Shopify had a file extension whitelist in place (meaning only approved extensions like .svg were allowed), but the SVG decoding was not properly implemented at the endpoint.
The vulnerability allowed an attacker to upload a maliciously crafted SVG file that contained an XSS payload using XML entities.
The Exploit Mechanism: SVG Payload
The attacker used the following SVG code, which leverages an external entity within the Document Type Definition (DTD) to define and execute the XSS script:
DOCTYPE >svgstrong> [
!ENTITY % strong>spstrong> "script>alert(1)script>">
!ENTITY % strong>spxstrong> "!ENTITY % elem '%sp;'>">
%spx;
]>
&elem;When this SVG icon was uploaded and then accessed by a victim, the browser would:
- Parse the SVG file.
- Process the DTD, which defines an entity (
sp) containing the XSS payload (). - Execute the entity reference
&elem;, which resolves to the XSS payload.
The Cross-Domain Attack Chain
This vulnerability was not only a Stored XSS but also demonstrated vulnerability chaining:
- Stored XSS: The malicious SVG file was stored on Shopify’s servers.
- Execution Points: When a victim viewed the Shopify Partner’s Dashboard or a Shopify store’s Admin Dashboard (
$storename$.myshopify.com/admin/), the icon was loaded, and the script was executed. - Social Engineering & OAuth: The attacker had to convince a victim to integrate the malicious sales channel app into their Shopify store via an OAuth authorization link:
Once the app was integrated, the stored SVG icon would load in the victim’s admin panel, triggering the XSS alert box./admin/oauth/authorize?client_id=...&scope=read_products&redirect_uri=...&state=nonce
Key Learning from this Report
- Look for Flaws in Whitelists: Do not trust that whitelisted file types are safe. Always test file formats like SVG and PDF, as they can embed executable code (XML and JavaScript) that bypasses basic string filtering.
- XSS Chaining: This case demonstrates chaining a Stored XSS (via SVG upload) with an OAuth workflow and social engineering to achieve high-impact exploitation.
- Cross-Domain Execution: The XSS was injected on one domain (
partners.shopify.comor the upload endpoint) and successfully executed on others ($shop$.myshopify.com/admin/). This was possible due to a permissive Cross-Origin Resource Sharing (CORS) policy or simply how the application served the file content, allowing the browser to execute the code in the victim’s session context.
Twitter XSS Case Study: Redirect Parameter Bypass
This report illustrates a vulnerability in a seemingly benign function—URL redirection—that was exploited to achieve XSS by confusing the application’s URL parsing logic.
| Field | Detail |
|---|---|
| Title | [dev.twitter.com] XSS and Open Redirect |
| Reported by | Sergey Bobrov |
| Bounty Rewarded | $1,120 |
| Application | Twitter Developer Platform (https://dev.twitter.com) |
Vulnerability Description
The vulnerability was identified on the dev.twitter.com domain within a redirect parameter (typically used in OAuth or login workflows). This is an example of an Open Redirect vulnerability that was successfully escalated to an XSS attack.
The issue was caused by a difference in how the application’s logic (backend) and the browser’s URL parser handled special characters in the redirect URI, allowing the attacker to bypass the whitelisting or sanitization rules.
The Exploit Mechanism: Redirect Logic Confusion
The attacker first identified that the application could be tricked into redirecting to an external site by using unusual characters after the protocol, bypassing the domain validation:
- Open Redirect Payload:
https://dev.twitter.com/https:/%5cshahmeeramir.com/- Resulting Redirection (
locationheader):location: https:/\shahmeeramir.com
%5cis the backslash character\) were used, resulting in an immediate redirect to an attacker-controlled domain. - Resulting Redirection (
The attacker then escalated this to an XSS payload by substituting the target domain with a JavaScript URI and introducing a new protocol, which the application failed to filter out completely:
- XSS Payload:
https://dev.twitter.com//x:1/:///%01JavaScript:alert(document.cookie)/ - Malicious Redirection (
locationheader):location: //x:1/://dev.twitter.com/JavaScript:alert(document.cookie)
The Client-Side Execution
The core XSS occurred because the final redirect page—the middleware page—used the unsanitized malicious URI within its HTML body.
The browser would display a message like:
You should be redirected automatically to target URL: JavaScript:alert(document.cookie). If not click the link.
By embedding the malicious JavaScript:alert(document.cookie) as the redirect link’s target, the application failed to filter the URI, and when the user’s browser rendered the link, the code would often execute, or the user would be tricked into clicking it, causing the script to run in the dev.twitter.com context and steal cookies.
Key Learning from this Report
- Test Redirect Parameters Exhaustively: Always check redirect parameters, as they often display the target URI without proper filtration in the HTML content of the middleware pages. These pages, which act as a security buffer before redirecting, are often overlooked by whitelisting mechanisms.
- Vulnerabilities in GET Requests: Even if an input parameter is not obviously displayed on the page, always look for vulnerabilities in all GET request parameters. These are frequently used for behind-the-scenes actions like redirection, where validation is sometimes lax.
XSS in Major Applications
To conclude the discussion on Cross-Site Scripting, here are several real-world examples, extracted from actual bug bounty reports, that illustrate the variety and impact of XSS vulnerabilities found in major applications.
1. Shopify Wholesale (Reflected XSS via “Magic URL”)
This report demonstrates how a vulnerability can exist even without a visible parameter name, relying on the application’s unique URL routing.
| Detail | Description |
| Vulnerability Type | Reflected XSS |
| Date Reported | December 21, 2015 |
| Reporter | kranko |
| Exploit URL | https://wholesale.shopify.com/asd%27%3Balert%28%27XSS%27%29%3B%27 |
The Exploit
The vulnerability was found in the application’s custom URL structure, sometimes referred to as a “Magic URL,” where each path segment (or “word”) in the URL is treated as an input parameter by the backend routing logic. This is common in applications that auto-generate URLs, like blogs or online stores.
The attacker was able to inject an encoded payload into the path segment:
%27%3Balert%28%27XSS%27%29%3B%27decodes to' ; alert('XSS') ; '
When the server failed to validate or encode this path segment before reflecting it into the HTML, the script executed, confirming a Reflected XSS.
Original Report Link: https://hackerone.com/reports/106293
2. Shopify Gift Card Cart (Reflected XSS in Form Data)
This report highlights the importance of testing every field within a form submission, even those related to file uploads.
| Detail | Description |
| Vulnerability Type | Reflected XSS |
| Date Reported | December 22, 2015 |
| Reporter | Juhhga |
| Vulnerable Parameter | properties[Artwork file] within Content-Disposition: form-data; |
The Exploit
The bug hunter discovered that the Artwork file parameter, sent within a multipart/form-data POST request (typically used for file uploads), was vulnerable to XSS. By inserting JavaScript code into this field’s value, the script was reflected back to the user, proving the lack of input validation on file metadata fields.
Original Report Link: https://hackerone.com/reports/95089
3. Shopify Currency Formatting (Stored XSS)
This bug is a slightly more complex example of Stored XSS, found in an administrative configuration panel.
| Detail | Description |
| Vulnerability Type | Stored XSS |
| Date Reported | December 14, 2015 |
| Reporter | Ivan Gringorov |
| Vulnerable Location | Form fields used to customize links and currency display. |
The Exploit
The researcher discovered that fields used to customize the display of the store’s currency formatting and personalized links did not properly validate user input.
- The attacker injected a malicious script into these customization fields.
- The script was stored in the application’s database.
- When any user (potentially including a store administrator) accessed the application, the saved, unvalidated data was retrieved and rendered, causing the script to execute.
This type of bug can lead to admin-level session compromise.
Original Report Link: https://hackerone.com/reports/104359
4. Yahoo Mail (Stored XSS via Auto-Generated HTML)
This high-value report demonstrates how XSS can be introduced through the application’s own auto-generated code snippets.
| Detail | Description |
| Vulnerability Type | Stored XSS (in an email client) |
| Date Reported | November 29, 2016 |
| Reporter | Jouko Pynnönen |
| Bounty Rewarded | $10,000 USD |
| Vulnerable Parameter | data-url within an HTML snippet for file attachments. |
The Exploit
The vulnerability was in the Yahoo Mail editor. When a user clicked to “Attach files from computer,” Yahoo Mail automatically generated an HTML snippet of code to represent the attachment within the email body.
The auto-generated HTML included a vulnerable data-url parameter. The attacker crafted an email where the attachment link pointed to a malicious JavaScript URI:
a href="...a.txt" data-url='javascript:alert("XSS")'>...a>By injecting the payload into the data-url attribute, the script was stored as part of the email content. When the victim viewed the email in the vulnerable editor, the browser executed the script. This is particularly dangerous as it turns the email client itself into a vector for a Stored XSS attack.
Original Report Link: https://klikki.fi/adv/yahoo2.html
5. Google Image Search (Reflected XSS with Time Delay)
This example is notable for its use of an obscure XSS execution vector—requiring a user action (pressing the Tab key) and a time delay.
| Detail | Description |
| Vulnerability Type | Reflected XSS |
| Date Reported | September 12, 2015 |
| Reporter | Mahmoud Gamal |
| Vulnerable Parameter | imgurl |
The Exploit
When a user opened an image in Google Search using the “Open in new tab” option, a complex URL was generated that included the image source in the imgurl parameter.
The researcher found that the imgurl parameter could be manipulated to contain a JavaScript URI payload using the url parameter within the final redirect chain:
...&url=javascript:alert(1)&psig=...
The unusual part was the execution. The XSS was not launched immediately. The browser required the user to press the Tab key to interact with the element containing the vulnerable script. After a short period of time following this interaction, the XSS script was executed. This demonstrates that even delayed or interaction-dependent script execution can constitute a valid and reportable XSS vulnerability.
Original Report Link: https://mahmoudsec.blogspot.com/2015/09/how-i-found-xss-vulnerability-in-google.html
Summary of XSS Detection and Mitigation
The real-world examples and technical discussions highlight crucial lessons for security professionals:
Persistence and Variants: Be persistent and use a wide range of payload variants and encodings (URL, HTML, Base64). Developers often use simple blacklists that can be easily circumvented. Finding a bypass just requires time and creative testing.
XSS is an Input Validation Error: All XSS vulnerabilities ultimately derive from a fundamental lack of proper input validation and output encoding controls on the server-side.
Test All Inputs: Review not just the fields in standard HTML forms, but all input data in an application, including:
URL path segments (Magic URLs).
GET request parameters.
Hidden form fields and file metadata.
Parameters used in the application’s control flow.
Utilize an HTTP Proxy: Always use an HTTP proxy (like Burp Suite or OWASP ZAP) to analyze and modify HTTP requests, allowing you to bypass client-side security controls and test the back-end logic directly.
