Are you still confused about the difference between Reflected XSS and DOM XSS?

8 min readJun 1, 2024


DOM-based xss

Today, we will explain the most challenging type of XSS vulnerability, which is DOM-Based XSS. However, today’s explanation will make this type easier for you, just read attentively. We will explain using the Portswigger Lab to simplify the information delivery. The LAB’s title we will be working on is “DOM XSS in document.write sink using source”.

If you prefer watching a video explanation on YouTube to understand the information more clearly and quickly, I recommend watching this video, which explains in detail what is being discussed here in this article.

First Step:

We will conduct a DOM analysis

After entering the LAB, we will input any value not present on the site, for example, ‘gentil’. When we type ‘gentil’ into the search box, we will notice that it is printed twice within the DOM, once between the <h1> tag and another time within the <img> tag, specifically within the src.

DOM Source Code
DOM Source Code

And we will notice that the <img> tag is being passed the value through JavaScript, and here we will pause for a moment to understand what is happening.

What is the value being passed to the <img> tag?

The word being searched in the search box is what’s passed to the <img> tag. In our case, the word ‘gentil,’ which we searched for in the search box. How is it passed to the <img> tag? Through JavaScript code.

Why is this passed to JavaScript code?

To understand why the designer passes the value entered in the search box to JavaScript, we need to analyze the JavaScript code to understand its purpose. This JavaScript code we see is responsible for taking the words searched in the search box within the page and sending them to the server to be stored all together in one place.

What benefit does the website owner gain from collecting the words searched within their site?

Simply put: To enhance the content they provide. When they know what is frequently searched within their site, they can focus on it and prioritize it.

For example: If their website is specialized in cybersecurity and the most searched queries within their site are related to penetration testing tools, they would heavily focus on providing content about penetration testing tools.

This means that without this JavaScript code, will the search process work without any issues?

Yes, exactly. This code does not affect the search process within the website, so it can be easily dispensed with completely, and the search process will continue to function efficiently.

Second Step:

In a DOM-Based XSS vulnerability, you must read and analyze the code to identify if there are any errors that could be exploited as a penetration tester.

So, we will now analyze the above JavaScript code to understand how the developer retrieves the value entered in the search box, and what is the error that led to the DOM XSS vulnerability.

function trackSearch(query) {
document.write('<img src="/resources/images/tracker.gif?searchTerms='+query+'">');

var query = (new URLSearchParams('search');

if(query) {

Firstly, the objective:

The developer wants to send the searched words to the server. To achieve this, they chose to execute this task using an img tag, specifically within the src attribute. To understand this, when the img tag requests a specific image from the server, it writes the path of the desired image inside the src attribute.

Like this:

<img src="/resources/images/tracker.gif" />

In this case, this is the path of the image requested from the server: /resources/images/tracker.gif

After understanding that the img tag communicates with the server, how will the developer send the value entered in the search box along with the img request?

The Developer will send the value entered in the search box to the server by writing it inside the src attribute of the img tag.

after /resources/images/tracker.gif

To make it look like this

Now let’s understand: the question mark “?” means “and”, as if it’s saying to the server,
Hey server, I want you to fetch the image at this path /resources/images/tracker.gif, and, server, take this value ‘gentil’ and store it in searchTerms and keep it on the server because I’ll need it later.

The server responds in the response, saying, “Here is the image you requested from me, and don’t worry, I’ve saved the value you sent me in searchTerms on the server, and you can retrieve it at any time if you need it.”

Now we understand that the programmer exploits the request for the image from the server to send the value entered in the search box and save it within it.

Where is the image? And why did they choose this particular method to send the search values to the server?

The image has a size of 1x1 pixel, so you won’t see it because it’s extremely small and not noticeable. In fact, the purpose of calling this image from the server is not to display it within the website. The designer simply used this method because it’s straightforward, uncomplicated, and doesn’t affect the page processing speed to send the search values within the website. Unfortunately, they wrote it in an insecure manner, leading to a DOM-Based XSS vulnerability. This also explains why the designer specifically chose this method to send the values to the server and store them within it.


To understand how the programmer retrieves the value we entered and passes it within JavaScript.

var query = (new URLSearchParams('search');

In this line, the designer retrieves all parameters, including the parameter related to the search box, using Then, they send all the parameters to a URLSearchParams object to extract the value of the ‘search’ parameter, which is what we searched for, and store it in a variable named ‘query’. Later, this variable is sent to a function that takes the value of this query and adds it inside the img request we discussed earlier. The function works like this.

function trackSearch(query) {
document.write('<img src="/resources/images/tracker.gif?searchTerms='+query+'">');

document.write is part of the DOM and its function is to write HTML code inside the page using JavaScript code. Inside it, there’s (‘<img src=”/resources/images/tracker.gif?searchTerms=’ + query + ‘“>’). Here, it tells the server that the value of searchTerms will be the query, and the query is the word the user searched for.

In this way, it has sent the value we searched for inside the search box to the server and stored it within it for later use without the need for the user to click on the page and without writing complex JavaScript code.

Third step:

To understand the error committed by the developer in writing the JavaScript code that led to the DOM XSS vulnerability.

function trackSearch(query) {
document.write('<img src="/resources/images/tracker.gif?searchTerms='+query+'">');

In this code, the developer took the value that the user searched for and passed it to JavaScript without encoding it, without encrypting it.

To fix this code to be secure, it should be written like this:

function trackSearch(query) {
var img = document.createElement('img');
img.src = '/resources/images/tracker.gif?searchTerms=' + encodeURIComponent(query);

So here, encodeURIComponent(query) is used to encode the value entered by the user in the search box. Then, it is added to the page using the DOM like this: document.body.appendChild(img).

This way, we have encoded the inputs and achieved the desired result in a secure manner.

Fourth step:

How to inject alert function into the search box?

First, let’s take another look at the img tag because we’re going to inject the code into it. It’s the final result written inside the DOM.

<img src="/resources/images/tracker.gif?searchTerms=gentil">

You can easily find out how to inject JavaScript code inside an img tag by searching on Google, and you’ll find thousands of results. The injection will look like this:

gentil" onload="alert('XSS')

In the end, it will look like this.

<img src="/resources/images/tracker.gif?searchTerms=gentil" onload="alert('XSS')">

Here, I closed the double quotation mark and then added an attribute called “onload,” which means when the page loads, execute the value I give you. In this case, the value is alert(‘XSS’).

So, when taking this payload “gentil” onload=”alert(‘XSS’)” and adding it into the search box, then pressing Search, the alert function code will be executed like this.

alert function
Portswigger DOM XSS LAB Solved

Now let’s address the most common question:

What is the difference between Reflected XSS and DOM-Based XSS?


The previous illustration highlights the fundamental difference between Reflected XSS and DOM-Based XSS.

Reflected XSS:

Reflected XSS cannot interact directly with the browser; there must be an intermediary between you and the browser to execute JavaScript code.
For example:
You tell the compromised server with a Reflected XSS vulnerability to return “123” to you in the request (“Please return 123 to me”) and return it as is in the response. It indeed takes your request and reflects it back to you as you requested, without making any changes to it (reflects it back to you again). This is what Reflected XSS does; it forces you to deal with the server to execute what you request on the browser. The browser trusts the server, not you, so it acts as the intermediary between you and the browser.

DOM-Based XSS:

In DOM XSS, you communicate directly with the browser without the need for an intermediary (server). The code you enter in the vulnerable location will be executed directly on the browser without the browser seeking permission from the server. The code you give it in the vulnerable location will be executed immediately.

This is the basic difference between Reflected XSS and DOM-Based XSS. I hope you enjoyed the article, and don’t forget to follow if you’re interested in Web Application Penetration Testing, Bug Bounty, and Cybersecurity in general. I also invite you to subscribe to my YouTube channel, which contains important videos for anyone interested in starting or advancing in the field of Web Application Penetration Testing and Bug Bounty. We are currently recording a course, and its episodes are released daily on the channel to take you from beginner to expert level, God willing.

Youtube Channel:

I also invite you to follow my accounts on social media if you’re interested in getting the latest cybersecurity news or if you have any inquiries. Don’t hesitate to reach out to me at your earliest convenience.