Cross-Site Scripting (XSS)
Cross-Site Scripting (XSS) is a type of security vulnerability commonly found in web applications. It happens when an attacker manages to inject malicious scripts (usually JavaScript) into a website, which then runs in the browsers of other users.
Because the browser trusts content from the website, the injected script can perform actions like:
-
Stealing cookies or session data
-
Redirecting users to malicious websites
-
Displaying fake content or phishing forms
-
Performing actions on behalf of the user
Three main types of XSS
There are three main types of XSS. Each ends with a script running in a victim's browser, but the script comes from a different place.
- Stored XSS: the script is saved on the server in a database and sent to every visitor.
- Reflected XSS: the script is in the request, such as a URL, and the server echoes it straight back.
- DOM-based XSS: the page's own client-side JavaScript writes untrusted data into the page.
Stored XSS
In stored XSS, the attacker's script is saved on the server, in a database, a comment, a forum post or a user profile. The server then serves it as part of the page to every visitor who views it.
This makes it the most dangerous type. One post can hit many users, and they do not have to click anything special. Just opening the page is enough.
In a stored XSS attack, where is the malicious script kept?
Why is stored XSS often seen as the most dangerous type of XSS?
Reflected XSS
In reflected XSS, the script is part of the request, such as a URL parameter or a search box. The server echoes it straight back in the response, so it runs in the victim's browser.
The script is not stored anywhere. The victim usually has to be tricked into clicking a crafted link, often sent in a phishing email or message.
DOM-based XSS
In DOM-based XSS, the server response is fine. The problem is the page's own client-side JavaScript. It takes untrusted data, such as location.hash or a URL parameter, and writes it into the page.
If the code uses something like innerHTML, any script in that data runs. The whole attack happens inside the browser.
An attacker emails a link to a shop's search page. The link's search term contains a script, and the server copies the search term straight into the results page. Which type of XSS is this?
A page's JavaScript reads location.hash and writes it into the page using innerHTML. The server's response is unchanged. Which type of XSS is this?
Where does a DOM-based XSS attack take place?
The three types of XSS compared
How to Prevent XSS
How to Prevent XSS
-
Validate and sanitize user input to remove dangerous characters.
-
Escape output when displaying user-generated content on webpages.
-
Use security headers like Content Security Policy (CSP).
-
Avoid inserting untrusted data directly into HTML, JavaScript,
Example: a vulnerable comment page
Here is a vulnerable Python function. It builds HTML by joining a stored comment straight into the page, with no escaping:
def show_comment(comment):
return "<p>" + comment + "</p>"An attacker posts this comment as their payload:
<script>alert('XSS')</script>The comment is saved, so the browser runs the script for every visitor who opens the page. A real attacker would swap the alert for code that steals session cookies.
Fixing the example
The fix is to escape the comment before it goes into the HTML, using html.escape():
| Vulnerable | Fixed |
|---|---|
def show_comment(comment):
return "<p>" + comment + "</p>" | import html
def show_comment(comment):
return "<p>" + html.escape(comment) + "</p>" |
The attacker's comment now comes out as:
<script>alert('XSS')</script>
The browser now displays the text instead of running it. For DOM-based XSS, use textContent instead of innerHTML.
In the vulnerable show_comment example, which change stops the attacker's comment from running as a script?
Complete! Ready to test your knowledge?
Cross Site Scripting (XSS)
- Cross-Site Scripting (XSS)
- Three main types of XSS
- Stored XSS
- Reflected XSS
- DOM-based XSS
- The three types of XSS compared
- How to Prevent XSS
- Example: a vulnerable comment page
- Fixing the example