The Cross-Site Scripting aka XSS Vulnerability

Bertin Loïc
Committed Engineers — by Per Angusta
8 min readMay 19, 2020

My name is Loïc and I’m a committed trainee at Per Angusta. Let’s talk about one of the most common type of security loophole. I’m pleased to share with you my first experience with Cross-Site Scripting.

Figure 1: My main detection tool

I’ll begin by presenting two cases where such vulnerabilities have affected famous companies. Next, I’ll talk to you more generally about what XSS vulnerabilities are. I will then give you two examples of typical situations where I’ve encountered them. Finally, I’ll make you a feedback on how I proceeded to locate them during one of my projects.

1. A BRIEF HISTORY

In 2010 the famous social network Twitter has been victim of a security breach. Untimely retweets, pop-ups, alerts and even automatic redirections, all you had to do was hovering messages to be confronted with it. The situation even got worse when a second version of the malicious code has been injected, its mere presence in your timeline was enough to spread it. For example, the wife of the British Prime Minister published a post to her millions followers that was sending them to a pornographic site when simply hovering it.

It was in 2014 when Paul Kerr, a Scottish computer scientist discovered a false ad on the eBay site. When he tried to access the details of the object in question he was automatically redirected to a replica of the login page (in order to retrieve his personal identifiers), he made a video of the phishing. Hundreds of ads following the same logic have been discovered afterwards.

2. GENERAL PRESENTATION

The previous examples were made possible through one of the most common vulnerabilities on the net: Cross-Site Scripting. It has been present for several years in the top 10 of the Open Web Application Security Project (OWASP). As a reminder, its abbreviation XSS has been chosen to avoid any confusion with CSS (Cascading Style Sheets).

2.1 WHAT IS THIS ALL ABOUT?

XSS vulnerabilities are a type of security breach that occurs when a piece of code injected by a third party user is interpreted by a web browser without any prior filtering action.

Its exploitation vectors are multiple due to the fact that the attacker can operate through any language supported by the browser (JavaScript, CSS, JSON…).

The most common uses of such a vulnerability are cookie theft and redirection to a copy of a site for phishing purposes.

For a good understanding of this article, it is important to understand that this kind of loophole is potentially present in every place where it is possible to interact with the site by transmitting information to it. This includes any action that submits data to your website: a comment space, an edit field, a search bar…

2.2 EXISTING CATEGORIES

It is possible to classify this security breach into three categories, each one with its own level of criticality. In addition, it is also possible to define it according to the terms “persistent” or “non-persistent”, we’ll come back to this last point later.

2.2.1 Reflected XSS

This type of vulnerability is the most common, it occurs when an input provided by the client-side is interpreted as is by the server-side to produce a result page. This loophole is generally considered as minor since the user can only disrupt his own pages (just refresh them to get back to a classic behavior).

2.2.2 Stored XSS

Let’s talk about the potentially most problematic kind. The principle is the same as before but this time the injected code is stored in a database making all users of the application potentially vulnerable due to its wide spreading (see the example of Twitter).

Thence, it is possible to envisage a large-scale data theft if such a loophole were exploited on a site such as a social network. It is also one way to get an administrator access to a website.

2.2.3 DOM-Based XSS

The particularity of this breach is that it never interacts with server-side. Indeed, attacks on the DOM are based only on client-side. As above, it requires that the targeted application contains a page using data from an unsecured object (such as document.location, document.URL or document.referrer), the hacker is able to influence it.

It requires an action by the victim. Therefore, we’re faced with a situation where social engineering can be employed.

Let’s imagine that the property document.URL is exploited in an unsecured way on the home page of a site and you click on the following link after being tricked:

          https://my-targeted-website.com/home.html?name=
<script>alert(document.cookie)</script>

In this case, when document.URL is called your cookies are displayed using the alert method. However, in a more realistic scenario, those cookies would be sent to a remote server without your knowledge.

3. EXAMPLE IS BETTER THAN PRECEPT

As part of one of my projects, I performed an XSS lookup. De facto, I’ll present two examples illustrating the main places where I met them, I’ll also talk about their resolution.

3.1 NON-PERSISTENT BREACH

Let’s say there is a field that allows you to search among the users of an application. As long as nothing is written there, a list of them is displayed below. In addition to this, a system that allows to refine a search in real time according to what is typed inside is intended.

Figure 2: Illustration of the example above

At some point, the entry provided is processed. Hence, without protection of the latter we have a typical case of non-persistent vulnerabilities. In other words, any piece of code inserted there is immediately interpreted.

3.2 PERSISTENT BREACH

Now let’s look at a case of persistent loophole. You’re editing your profile and choose to change your nickname. This will most likely be done through a form, so imagine that you choose an original moniker like the one below:

   <script>window.location.replace("https://medium.com/")</script>

Once your change is validated, let’s say you go to the page of your profile where your new nickname is displayed. As previously, we have a situation where an entry provided by a user is interpreted: if once again the data are not protected you’re redirected to the URL above.

The difference with the previous example is that the injected piece of code is persistent in the database as long as the record is not modified or deleted. Moreover, if someone else goes to your profile, he would be redirected in his turn. Understand here that because it is persistent this vulnerability can affect all users of your application.

3.3 RESOLUTION

Nevermind if the breach is persistent or not and whatever language you use, the context for such vulnerabilities is always the same: a line of code that has nothing to do there has been interpreted as such by the Web browser.

It is thus a question of encoding certain characters (“, <, >…) or simply deleting certain portions of a string (for instance the script tags).

Such methods exist for all languages, I used encodeURI in JavaScript and html_escape in Ruby. They’re obviously not the only ones existing (cf. encodingURIComponent, sanitize, html_escape_once…).

4. LOCALISATION

We’ve talked about what XSS vulnerabilities are and how to avoid them. However, you’ll have to locate them first.

De facto, I’ll now share with you the way I proceeded through a feedback. I would like to take this opportunity to remind you that my purpose is by no means to say that my method is the right one.

For your information, automatic detection tools do exist, isn’t it paradoxical that they can be used for prevention as well as for exploitation?

4.1 QUESTIONINGS

I started from a simple assessment: An XSS vulnerability operates when a piece of code injected by a user is interpreted by the web browser without prior security.

In a perspective of global search through the application I first asked myself where to find the most possible occurrences corresponding to this description. The keywords that appeared to me as the most relevant were paradoxically the name of the Rails method which indicates that there is no risk to interpret a data: html_safe.

Consider the following example:

           <%= "#{user.name}<br>#{user.tel}".html_safe %>

This method doesn’t actually make a string safe for HTML rendering, but only is a manual marker to tell the view renderer engine that the string has already been made safe and that it should be rendered as is.

This is typically a case where we have to escape user.name and user.tel.

I first looked to see if this method was called a lot and I’ve been astonished: more than 900 occurrences. So I ruled out treatment on a case-by-case by this bias.

It had been suggested to me that there might be some weaknesses in the helpers so I started looking into them. There were plenty of them and for the most part related to portions of the application that I’d never touched. To be honest, it confused me above all.

From there, in order to avoid a huge lookup work I made the decision to break out of the code and put myself in the shoes of an attacker. To do so, I simply tried to get as many fields as possible to interpret the famous :

       <script>alert("Oh no... Here we go again!")</script>

4.2 THE BRUTE-FORCE METHOD

Although a priori laborious and redundant, this search method brought out several points that I considered positive.

Figure 3: Illustration of the Brute-Force method

First of all, testing as many fields as possible allowed me to see the application much more in depth (both on the business side and on the code side).

On the other hand, I assume that starting from the vulnerability to the code and not the opposite way allowed me to save a lot of time.

In addition, it gave me the opportunity to gain granularity by gradually identifying redundant patterns and thus to deal with certain cases in a more refined and systematic way.

4.3 BACK TO HELPERS

After testing all the fields I was able to identify I thought it might be interesting to go back to the helpers.

My previous search gave me a much better understanding of them so I’ve started a second round through them. It was much easier for me to find my way from that moment and thus to be able to finish the tour of the loopholes I thought I could found.

5. THE FINAL WORD

According to OWASP: Cross-Site Scripting vulnerability is present in more than two thirds of websites and is more generally the second kind of breach on the net. Reflected/Dom-Based XSS are categorized as moderate risks whereas Stored XSS are identified as severe.

As these three sub-types of loopholes are now detectable in an automated way, it is therefore not negligible to set up protections against them.

I hope that this story was enjoyable to you as much as I liked discovering this vulnerability :-) keep safe with XSS!

NB: An easter-egg is hidden somewhere…

Interested in joining an enthusiastic engineering team?
We are recruiting talented people! Checkout our open positions here:

--

--