XSS Attack Example: A Deep Dive for Pentesters & Bug Bounty Hunters
A Cross-Site Scripting (XSS) attack example typically involves an attacker injecting malicious client-side script, most often JavaScript, into a web page viewed by other users. This allows them to bypass client-side security mechanisms, steal session cookies, deface websites, redirect users, or even execute arbitrary code within the user's browser context. For pentesters and bug bounty hunters, understanding XSS isn't just academic; it's a fundamental skill for finding critical vulnerabilities in modern web applications.
Understanding Cross-Site Scripting (XSS) Attacks
What Exactly is XSS and Why Does It Matter?
At its core, XSS is about trust. Your browser trusts the code it receives from a website. When an attacker successfully injects their own script, your browser executes it, believing it's legitimate code from the site. This trust bypass is what makes XSS so potent.
The impact of a successful XSS attack can range from annoying pop-ups to full-blown account compromise. An attacker could:
- Steal session cookies: Gaining access to a user's authenticated session without needing their password.
- Deface websites: Altering the content of a page, often for propaganda or protest.
- Redirect users: Phishing for credentials on a malicious look-alike site.
- Perform actions on behalf of the user: If the user is an admin, an XSS payload could create new admin accounts.
- Keylog sensitive information: Capturing keystrokes as the user types.
- Trigger client-side exploits: Leveraging browser or plugin vulnerabilities.
I've seen XSS vulnerabilities persist for years in applications simply because developers didn't grasp the full implications of untrusted input. It's not just about filtering <script> tags; it's a much deeper issue.
Key Takeaway: XSS exploits the browser's trust in a website's content. Successful exploitation gives an attacker control over the victim's browser session within the context of the vulnerable application, leading to data theft, defacement, or unauthorized actions.
The Three Flavors of XSS: Reflected, Stored, and DOM-based
While the end goal of XSS remains similar, the method of injection and how the payload persists (or doesn't) defines its type. Knowing these distinctions helps you craft more effective payloads and defense strategies.
Here's a quick rundown:
| XSS Type | Description | Persistence | Attack Vector Example |
|---|---|---|---|
| Reflected XSS | The malicious script is reflected off the web server immediately in an error message, search result, or any other response that includes some or all of the input sent by the user as part of the request. | Non-persistent (requires victim to click a malicious link) | Malicious URL containing payload sent via email/chat. |
| Stored XSS | The malicious script is permanently stored on the target server (e.g., in a database, forum post, comment field, or visitor log) and then delivered to other users without any further interaction from the attacker. | Persistent (stored on the server, affects all visiting users) | Comment section, user profile, blog post. |
| DOM-based XSS | The vulnerability arises in client-side code rather than server-side. The payload is executed as a result of modifying the Document Object Model (DOM) environment in the victim's browser, typically due to client-side scripts processing user input or URL fragments. | Non-persistent (but can appear persistent due to client-side logic) | URL fragment (`#` part), client-side JavaScript. |
Dissecting Real-World XSS Attack Examples
Theory is nice, but practical examples are what stick. Let's look at how these XSS types manifest in code and how attackers exploit them.
Reflected XSS Example: The Echo of Malice
Reflected XSS is the most common type you'll encounter in bug bounty programs and CTFs. It usually involves a server taking user input directly from a URL parameter and echoing it back to the page without proper sanitization.
Consider a simple search page (`search.php`) that displays the search query back to the user:
Vulnerable PHP Code (search.php):
<?php
$query = $_GET['q'];
echo "<h2>You searched for: " . $query . "</h2>";
?>
If a user visits `https://example.com/search.php?q=hello`, they see: "You searched for: hello".
Now, let's inject a payload. An attacker could craft a URL like this:
https://example.com/search.php?q=<script>alert('Reflected XSS!');</script>
When a victim clicks this link, the browser makes a request to `search.php`. The server receives the `q` parameter, embeds it directly into the HTML, and sends it back. The browser then renders the page, sees the `` everywhere. It requires a methodical approach, understanding how applications process input, and using the right tools.
Manual Testing and Browser Developer Tools
Your browser's developer tools are your best friend for hunting XSS. Here's my typical workflow:
- Identify Input Points: Look for search bars, comment fields, profile editors, URL parameters, hidden input fields, HTTP headers (especially Referer and User-Agent), and anywhere user-controlled data might be reflected.
- Simple Payload Test: Start with basic, non-disruptive payloads. My go-to is `'">` to break out of attributes and tags, followed by `` or `
`.
- Check the Source Code and DOM: After submitting a payload, right-click and "Inspect Element" or view the page source. See how your input is rendered. Is it HTML-encoded? Is it inside a ``.
- If it's inside a ``
- Using other event handlers: `onmouseover`, `onfocus`, `onblur`, `onclick`.
- Using less common tags: `<details open ontoggle=alert(1)>`, `<marquee onstart=alert(1)>`.
- Unclosed Tags: Sometimes an unclosed tag can be used. For example, `<script>alert(1)//` (the `//` comments out the rest of the line, potentially avoiding parsing issues).
- Data URIs: `<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></iframe>` (base64 encoded ``).
- Whitelisting: The most secure approach. Only allow known-good characters, patterns, or formats. For example, if a name field should only contain alphanumeric characters, only allow those.
- Blacklisting: Trying to block known bad characters or tags (like `
The OWASP XSS Filter Evasion Cheat Sheet is an excellent resource for a comprehensive list of bypass techniques. I keep it bookmarked.
Defending Against XSS: A Developer's and Pentester's Guide
As pentesters, we don't just find vulnerabilities; we help fix them. Understanding defense mechanisms is crucial for both sides of the coin.
Input Validation and Sanitization
This is your first line of defense. Always validate user input on the server side. Never trust client-side validation alone, as it's easily bypassed.