The majority of applications use JavaScript, and you must know that XSS is a JavaScript-based issue. Cross-site scripting (also known as XSS) is a web security vulnerability that allows an attacker to compromise users’ interactions with a vulnerable application. It allows an attacker to circumvent the same origin policy, which is designed to segregate different websites from each other.
Table of Contents
ToggleCross-site scripting vulnerabilities normally allow an attacker to masquerade as a victim user, to carry out any actions that the user can perform, and to access any of the user’s data. If the victim user has privileged access within the application, then the attacker might be able to gain full control over all of the application’s functionality and data.
Types of XSS:
There are 3 Types of XSS — Reflected, Stored, DOM.
Reflected XSS: It arises when an application receives data in an HTTP request and includes that data within the immediate response in an unsafe way.
Stored XSS: It arises when an application receives data from an untrusted source and includes that data within its later HTTP responses in an unsafe way.
DOM based XSS : It arises when an application contains some client-side JavaScript that processes data from an untrusted source in an unsafe way, usually by writing the data back to the DOM.
In this article, we will learn about DOM-based XSS, but before going to learn about DOM XSS, we should understand about DOM.
What is DOM?
DOM stands for Document Object Model; it’s a model that browsers use to render a web page. The DOM represents a web page’s structure; it defines the basic properties and behaviour of each HTML element and helps scripts dynamically access and modify the page’s content, structure, and style.
This all portion comes under DOM means you can do everything which comes under this portion.
What is DOM-based XSS?
DOM-based XSS is similar to reflected XSS, except that in DOM-based XSS, the user input never leaves the user’s browser. It is a cross-site scripting attack that allow attackers to inject a malicious payload in the web page by manipulating the client’s browser environment. But, before going in depth of this, we have to understand 2 terms which are sources
and sinks
.
Source: It is a Javascript property that accepts data which is controlled by the attacker is known as the source. For example, location.search
 property as this property reads input from the query string, which is easy to control by the attacker. This means that any property that the attacker can control is a potential source.
Common sources:
document.URL
document.documentURI
document.URLUnencoded
document.baseURI
location
document.cookie
document.referrer
window.name
history.pushState
history.replaceState
localStorage
sessionStorage
Sink: A sink is a potentially dangerous JavaScript function or DOM object that can cause undesirable effects if attacker-controlled data is passed to it. For example, the eval()
function is a sink because it processes the argument that is passed to it as JavaScript.
Common Sinks:
document.write()
window.location
document.cookie
eval()
document.domain
WebSocket()
element.src
postMessage()
setRequestHeader()
FileReader.readAsText()
ExecuteSql()
sessionStorage.setItem()
document.evaluate()
JSON.parse()
element.setAttribute()
RegExp()
DOM-based XSS vulnerabilities usually arise when JavaScript takes data from an attacker-controllable source, such as the URL, and passes it to a sink that supports dynamic code execution, such as
eval()
 orÂinnerHTML
. This enables attackers to execute malicious JavaScript, which typically allows them to hijack other user’s accounts.
Testing for DOM XSS
Testing for DOM XSS is not that easy as compared to Reflected and Stored XSS. We need to use the developer tools to test for this as the values will appear in the DOM, not in the source code.
Let’s understand this with example
Here for example purpose we are going to take a look of some Portswigger’s Lab.
- First Example→DOM XSS inÂ
document.write
 sink using sourceÂlocation.search
1) We will search some random string to check where our input is reflected on the next page.2) After clicking on search, we go to the page source. We only get 1 reflections of string
"iwantbug"
3) But when we search this string in our dev-tool, we get 2 reflections of string
"iwantbug"
4) As you can see, our string is getting reflected inside an
img src attribute
and we have to break out of theimg attribute
to insert our payload. You can see in the below image that we have inserted our malicious payload.5) As our payload is balanced, we should input our payload in search
payload :
iwantbug"><svg onload=alert(1)>
As of now, we have understood that how we got
alert
but let’s understand why this happen?
- Let’s dive in1) You can see in the
script tag
there is some JavaScript written which is the reason behind DOM-based XSS for this lab2)
window.location.search
is a source from which the input is taken and passed to sink. If I show you the value stored inquery
variable.3) This
query
is passed to the functiontrackSearch
4) Here you can see that our
query
is directly gets appended to thedocument.write
function (sink) without any sanitization, and this function writes data out to the page because of this our payload gets triggered.5) Here you can see our
query
data is written.6) In this way, Dom XSS get occurred.
If a Javascript library such as jQuery is being used, you can lookout for sinks as ${}(selector function)
which you can use to inject malicious objects into the DOM. JQuery used to be extremely popular, and a classic DOM XSS vulnerability was caused by websites using this selector in conjunction with the location.hash
 source for animations or auto-scrolling to a particular element on the page. As the hash is user controllable, an attacker could use this to inject an XSS vector into the $()
 selector sink.
1) You can see the page is loaded as usual. But what if anyone wants to directly show some particular post from this page that directly get shown as the page is loaded? In that case, we need to implement a hashchange
event.
2) For more understanding, let’s suppose we have to go to 3rd post of this page directly then. We will append post title after #
, and you can see we have reached now on 3rd post. Now I think you have got the feel of what hashchange
event does.
3) So what if I enter some malicious payload after #
😎 i.e <img src=x onerror=alert("Hello_dn0m1n8tor")>
Finally, our malicious payload got executed.
Let’s understand why we got our payload executed
1) This JavaScript code is responsible for the execution of our payload.
2) So here you can see window.location.hash.slice(1)
, let’s see what output we are getting from this. You can see we are getting all value after hash.
3) Here hash is user-controllable, an attacker can use this to inject an XSS vector into the source, and that gets passed to the ${} selector sink
. This is how our payload gets executed, and we get an alert.
- DOM Invader: Sometimes it becomes hard to identify were sink is present. As DOM XSS requires several tedious manual steps including trawling through complex, minified JavaScript. To help us with this manual work Portswigger come up with the tool names as DOM Invader, DOM Invader does a lot of this hard work for you, meaning you can identify interesting behavior in seconds rather than hours.
To configure Dom Invader follow the steps:
1) Open your Burpsuite and open browser
2) In browser PIN this extension.
3) Click on that Blue Burpsuite icon and turn on DOM Invader. Add canary token
( canary token is token which will be used by us to input in an input field of websites so that DOM invader can find out from where this token is getting pass to detect sources and sink) and click on reload
to reload your website which you were testing.
4) DOM Invader is setup perfectly.
Now we will see how to use this. Let’s consider the previous example that we have manually found sink and source.
- Getting to our example
1) We are going to put our canary token in input field and click on search.
2) After you clicked on search, open inspect
and go in Augmented DOM
As you can see here sink is shown document.write
,now click on Stack Trace
and open console
3) You can see trackSearch
, click on URL, which will take you to the actual line where the sink
is present
4) From here the things are same as we did in manual exploitation.
Prevention from DOM-based XSS
-
- Sanitize all untrusted data and always use user input as text content, never as HTML tags or any other other potential code.
- Avoid methods such as
document.innerhtml
and instead use safer functions, for example,document.innerText
anddocument.textcontent
. - Don’t eval() JSON to convert it to native JavaScript objects. Instead useÂ
JSON.toJSON()
 andÂJSON.parse()
.
Resources :
https://portswigger.net/web-security/cross-site-scripting/dom-based
https://owasp.org/www-community/attacks/DOM_Based_XSS
https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html