Web Security Vulnerabilities - Cross Site Scripting (XSS)
Table of Contents
- What is XSS?
- Types of XSS
- What is the Impact of XSS?
- How to Find XSS?
- How to Prevent XSS Attacks?
- Time to Practice
- Resources
- Conclusion
What is XSS?
Cross-Site Scripting, also known as XSS, is a web security vulnerability that allows attackers to inject malicious scripts into web pages viewed by other users. These scripts typically execute in the victim’s browser, leading to security breaches like account compromise, data theft, or website defacement.
XSS occurs when user input is accepted and reflected by the website without proper validation or sanitization. It allows attackers to impersonate victims and perform actions like stealing sensitive data or injecting malicious content into the webpage.
Types of XSS
- Reflected XSS
- Stored XSS
- DOM-Based XSS
- Blind XSS
Reflected XSS
Reflected XSS occurs when an attacker injects malicious code into a request, and the code is reflected in the response in an unsafe manner.
Example:
When you search for something on a website, the original request might look like this:
GET /search.html?q=test HTTP/1.1
And the response from the website might return your input like this:
<h1>
Your Seach: test
</h1>
If a malicious payload is injected, it might be returned and executed by the website.
Stored XSS
Stored XSS, also known as Persistent XSS, occurs when an attacker injects malicious code that is stored on the server of the website. This means the code will be executed on every visit without requiring the submission of the payload again.
Example:
Assume you are commenting on a blog post. The request might look like this:
POST /post/comment HTTP/1.1
Host: example.com
Content-Length: 100
postId=1&comment=It's+amazting&name=test&email=test@example.com
The comment will be stored on the server and displayed whenever any user visits the post.
If you inject a payload, it will be executed every time the page loads.
DOM-Based XSS
DOM-based XSS arises when malicious code is injected into the Document Object Model (DOM) of a web page. The vulnerability exploits the client-side JavaScript code, typically by manipulating variables, URL fragments, or other elements of the DOM.
Example:
In some applications, when you enter your name, the website might save your input in the DOM like this:
<script>
var name="test";
</script>
If an attacker injects malicious scripts into the variable, they would be executed in the context of the application, leading to XSS.
Blind XSS
Blind XSS, also known as Stored Blind XSS, occurs when an attacker injects malicious code into a vulnerable web application, but the injected code does not appear in the immediate response to the attacker. Instead, the injected code is stored on the server and later executed in a different context, which could be in another part of the same application or even in a different application altogether.
What is the Impact of XSS?
The impact of XSS depends on how and where the XSS vulnerability is exploited within the application.
- If an attacker compromises a user with
admin
privileges, the impact will be critical. - Attackers can steal session cookies, gaining unauthorized access to the victim’s account.
- If the XSS only causes a reflected alert popup and does not execute harmful scripts, the impact is considered low. It mainly affects user experience and indicates a security flaw.
- XSS allows the attacker to craft convincing phishing attacks by injecting fake content into a legitimate website.
How to Find XSS?
Manual Testing
To test if an application is vulnerable to Cross-Site Scripting (XSS), you should test all user inputs on the website and focus on:
-
What is reflected?
Check if the (full user input or part of it) is reflected in the response from the server, either immediately or after some processing.
-
How is it reflected?
Understand how the user input is reflected in the response. Is it reflected in HTML, JavaScript, or even CSS without escaping, what encoding used, or is it sanitized before displaying.
-
Where is it reflected?
Determine where the user input is reflected in the response. It could be in a URL parameter, a form field, a cookie, or other parts of the request or response. Some areas to focus on:
- HTML tags
- JavaScript code (
<script>
) - attribute values (like
href
,src
,onclick
) - URLs
- Cookies
- Dynamic content loaded via AJAX or APIs
- Filename when upload a file
- Search Bar
- Login pages
- Comment section
- Error messages
-
How the website deals with your input?
Test how the website handles different user inputs, such as special characters, JavaScript code, or HTML tags. See if the website filters or escapes user input to prevent XSS attacks.
-
Use XSS Cheat sheet for bypassing filters and WAFs.
Tip: Always test on different browsers as XSS vulnerabilities can behave differently across browsers.
Automated Testing
While I prefer manual testing for vulnerabilities, some scenarios require automation to make the work easier.
Here are some XSS automation tools you can use:
XSSer
- XSSer is an automated XSS vulnerability detection tool. It automatically identifies and exploits XSS vulnerabilities using different payloads.
XSStrike
- XSStrike is a powerful XSS detection tool that can automatically generate payloads and test for reflected and stored XSS vulnerabilities.
XSSHunter
- XSSHunter is used for testing
blind XSS
vulnerabilities, where the attacker cannot see the output directly. It helps set up payloads that can trigger when executed on other users’ browsers, sending a notification to the attacker.
Netsparker
- Netsparker is an automated web application security scanner that helps identify and prioritize security vulnerabilities, including XSS. It provides a user-friendly interface for both beginners and experienced security professionals.
How to prevent XSS attacks?
Preventing XSS vulnerabilities involves combination of the following measures:
-
Filtering user input: Never trust user input, always perform validation and sanitation on input from untrusted sources.
-
Encoding: Encode user input before incorporating it into response.
-
Disable Inline JavaScript Execution: use the following header to make the browser to block pages if XSS is detected:
X-XSS-Protection: 1; mode=block
. -
**Use
HTTPOnly
** attribute on cookies to prevent JavaScript access to sensitive session cookies. -
content Security Policy (CSP): Implement a strong Content Security Policy to restrict the types of content that can be executed within your application.
Content security policy (CSP) is the last line of defense against cross-site scripting. If your XSS prevention fails, you can use CSP to mitigate XSS by restricting what an attacker can do.
CSP lets you control various things, such as whether external scripts can be loaded and whether inline scripts will be executed. To deploy CSP you need to include an HTTP response header called
Content-Security-Policy
with a value containing your policy.Same Origin Policy (SOP)
Time to practice
Now let’s practice what we’ve learned and see how we can find XSS in real-world scenarios.
We’ll practice on 7 labs that I made. Let’s start with the first challenge.
Challenge #1
In the first challenge, we are asked to execute alert("XSS_Challenge_1")
and are provided with a GET
parameter called name
.
Let’s use this parameter normally and type some random text.
We can observe that our text is reflected on the web page.
Next, let’s try to inject some special characters to determine how the website handles user input.
As we can see above, the website returns user input in the response without any validation.
So, let’s intercept the request with Burp Suite and experiment with it.
In the image above, I tried to inject a <script>
tag, but it seems the website filters it. Let’s try injecting other tags like <img>
. The website reflects this as normal input, which indicates the presence of XSS.
Now, let’s try to execute XSS using this payload: <img src=x onerror=alert(10)>
.
We successfully solved the first lab.
<script>
tag bypass
As we saw earlier, the website filters out <script>
tags, but we can bypass this filter using <scrscriptipt>
.
This technique works if the application removes the <script>
tag only once.
As we can see above, it’s working, and we can execute alert(10)
.
Let’s solve the challenge and alert("XSS_Challenge_1")
.
Challenge #2
The second Challenge provides us with img
parameter to enter image name.
Let’s type an existing image name and determine how it works.
As we see above, it just displays an image., so let’s look at source code to identify where user input is inserted.
We can see image name is inserted in src
attribute.
So to execute XSS
, we need to escape src
attribute. Let’s do so using: test.jpg' onmouseover='alert(10)
.
As the payload was accepted, let’s solve the second challenge and alert XSS_Challenge_2
.
The second challenge is done. Let’s move to the next.
Challenge #3
The third challenge shows us the Guest Book
page with Name
and Message
parameters.
Let’s type random text in both parameters, and see how the website handles it.
As we see above it is store our input and display it in the web page. so let’s intercept the request to burp and try to exploit it.
If we inject some special characters and <script>
tag, we can see that the website store it without validation or filteration.
Now let’s exploit it and execute alert(10)
.
Challenge #4
This challenge from Idek
CTF is special as it has a new technique that I’m not used before. Let’s look at it.
Source Code:
We can see above, the page takes GET
parameter called name
and applies some filters to it.
If the value of name
parameter contains \n
, \r
, \t
, /
and ` “ “`, then it replace it with empty string.
Let’s see these filters in the page.
First try: <script></script>
Second try: <img src=x onerror=alert(10)>
We can see above how filters will prevent our payload.
If we search in google for XSS without spaces
, we will find this payload: <img/src/onerror=alert(1)>
.
But this will not work because it contains /
. So, let’s do another simple Google search: XSS with no spaces and slashes
.
We can found this technique, actually I’m not using this before, so you can search for it.
Now, If we try the above payload, it will work successfully.
Challenge #5
In the fifth challenge, We can see a search page. Let’s try to break it.
As we learned above the first step is to use the functionality as normal user.
We can see above, the page just reflect user input into the page. So let’s test for special characters and we can see that it doesn’t filter the output which is a sign to XSS.
Let’s try to break it and inject XSS payload: <script>alert(10)</script>
Challenge #6
In the sixth challenge, the website goal is to print the name in the web page with special font and provides us with name
parameter.
So, let’s type random text like HackerOne
and we can see that the name is reflected in the web page.
If we inject some special characters, the website reflected it like the first challenge.
If we try to exploit it again using <script>
, we will see that the website filters it.
Also if we try to bypass <script>
tag using <scrscriptipt>
, it won’t work.
So, let’s move to another tags like <img>
or <svg>
and both of them worked.
Now let’s exploit XSS
using svg
tag this time.
unfortunately the website shows us: Hack Detected
.
It may be filter some event handlers, so let’s try to use another one like: onmouseover
and it worked.
Challenge #7
This challenge like the previous challenge which also print the name in the web page with special font and provides us with name
parameter. so let’s check it and see what is different.
Again let’s inject some random text and special characters.
We can see above the website reflects user input without validation on special characters.
So, let’s inject <script>
tag, we can see the website accepts it without validation.
Let’s try to execute alert(10)
to solve the challenge.
Unfortunately, we can’t use alert
as it filtered.
We can use another functions like confirm
and prompt
, but all of them not working.
But we can bypass this filter and execute alert()
using eval()
and separate alert
into 2 pieces.
It is worked and we solve the lab.
The eval() function evaluates JavaScript code represented as a string and returns its completion value.
Resources
- PortSwigger - Cross-site Scripting (XSS)
- Intigriti - Cross-site Scripting (XSS)
- OWASP - XSS (Cross Site Scripting)
- Tryhackme - Cross-site Scripting (XSS)
- XSS Cheat Sheet by PortSwigger - Cross-site Scripting (XSS) Cheat Sheet
- OWASP WebGoat
- XSS Game by Google
- Bug Bounty Bootcamp book
Conclusion
XSS vulnerabilities, although common, can have severe consequences for applications and users alike. Understanding how XSS works and the different ways it can be exploited is essential for both developers and security testers.
With the combination of proper input validation, output encoding, and a robust Content Security Policy, XSS vulnerabilities can be effectively mitigated. Keep practicing with real-world challenges to improve your understanding and detection of XSS vulnerabilities!
Thanks for reading.