XSS Attack: Case Study

Michael Frank
11 min readFeb 26, 2021

With the aim of simplifying the collection of training data for neural networks, we at Labler have developed a marketplace where data scientists and software developers can buy and sell training data. In this article, we look at what a cross-site scripting (XSS) attack is and to what extent our marketplace is protected against it.

Labler — Functionality and technology stack

Before we talk about the XSS attack, we will first briefly describe the structure of the marketplace application and explain the technology stack behind it.

Labler is a marketplace for training data, so there are people who take the role of buyers and sellers on the platform and accordingly have different views and functionalities available. The development of the actual platform is not yet completed, but an MVP has been implemented so far. WordPress was used as the basis for the implementation and the basic buying and selling of training data was made possible with the help of the WooCommorce and Dokan plugins.

Labler technology stack

Security and privacy requirements

Labler works with a large amount of sensitive data, which under no circumstances should be accessible to attackers. This includes information such as personal data like names or addresses, billing data or credit card information. In addition, sellers trust Labler to manage their products securely. The sold data on the platform has a financial value and, accordingly, the theft of this data leads to a financial loss for the sellers.

In summary, Labler as a platform must offer the following securities:

  • Protection of users
  • Protecting and securing sensitive data
  • Protection and securing products of the vendors

Cross-site scripting (XSS) attack

Before we explain how an attacker could try to attack Labler using cross-site scripting, we will briefly explain the relevance of XSS attacks today and how the attack works.

Relevance of XSS attacks

Even today, cross-site scripting attacks are a problem of many web applications. In its 2020 vulnerability statistics report, edgescan, a company that analyses and deals with cyberattacks, found that the XSS attack is the second most common attack against full-stack web applications and one of the most critical.

How cross-site scripting attacks work

Cross-site scripting is a client-side attack in the browser where malicious source code, usually in JavaScript, is injected into the application. The malicious code can be injected through multiple ways, which will be later discussed. JavaScript offers the possibility to access browser data such as cookies, session tokens or storage data. As in the case of session tokens, this data is sufficient to impersonate another person, if one can get hold of it. For this reason, attackers try to get access to sensitive data by injecting JavaScript and sending it to themselves. All in all, it can be said that all the possibilities offered by JavaScript are available to the attacker in this type of attack. Here are a few actions an attacker can perform using an XSS attack:

  • Stealing sensitive data (personal data, payment data, etc.)
  • Redirection to phishing sites
  • Performing unauthorized action by stealing session tokens
XSS attack example

Types of cross-site scripting attacks

Reflected XSS

In the case of the Reflected XSS attack, the web application evaluates data (query strings) from the called URL and uses it in some way. There is a danger here that an attacker can prepare the URL and the transferred parameters in such a way that they contain an HTML script tag. If this malicious parameter is then used by the application, for example, to directly change the information in the DOM, the script is executed instead. This gives the attacker every possibility to steal data or manipulate the web application. The special feature of this attack is that the victim does not necessarily have to be a user of the application, but can simply be a person who clicked on the link and thus came to the page. In addition, this attack is easy to distribute quickly by sharing the link via open chats or social media. This is also one of the reasons why you should not necessarily open every link and should also look at it in advance.

Reflected XSS attack

Stored XSS.

In the Stored XSS attack, an attacker tries to bring the malicious script into the application’s system via input possibilities. Such attacks are often carried out in forums or chats, as there is an easy way to insert the scripts and they can also be received quickly by other users. In WordPress, there is also the additional risk that the server administrator of the WordPress application gets attacked. This is because the editor in WordPress is a content management system (CMS) with a normal web interface, which means that the injected script can also be executed there. If this attack is performed and works, the attacker uses the vulnerability that the data is not escaped in any form.

Stored / Persistent XSS attack

DOM-based XSS.

Similar to the Reflected cross-site scripting attack, the DOM-based cross-site scripting attack also takes place when the application DOM is manipulated. Again, the attacker tries to inject his code into the web application and to execute it, for example, when manipulating the DOM. The code, therefore, comes from an area that can be controlled by him and adapted accordingly. For this reason, the general use of JavaScript functions such as eval() is an inappropriate approach. eval() enables the parsing of a string as JavaScript code and can therefore be harmful.

DOM-based XSS attack

How to prevent XSS attacks?

XSS attacks can be prevented in several ways, although it is always necessary to evaluate the extent to which it makes sense to restrict something in exchange for reducing the risk of an XSS attack. This section presents some of the ways in which cross-site scripting attacks can be prevented.

Disable JavaScript

As already described several times, the XSS attack can only take place due to malicious JavaScript code executed on the client-side. For this reason, turning off JavaScript in the browser is a safe way to protect yourself against this attack. However, this probably has the consequence that many web applications do not work at all or only to a limited extent, because today’s web applications are heavily based on JavaScript. This is something you have to decide for yourself as a user, although I personally would not do this, as it would strongly limit the work in the browser and web.

Be careful with dynamic JavaScript execution

Dynamically executed JavaScript code can pose a risk in general, as has been frequently addressed by developers and researchers using the eval() function as an example. Especially with DOM manipulation, JavaScript is often executed dynamically, for example with the DOM element attribute innerHTML. With innerHTML, there is a danger that an attacker can bring a code snippet with a script tag into the application. If the web application then wants to change a DOM element and does this using innerHTML and transmits the malicious code precisely with this, it will be executed on the basis of the script tags. Since innerHTML is often used for text changes, it is a good idea to use secure alternative change options such as Node.textContent, which can prevent such an attack and also changes the text.

HTTP-Header X-XSS-Protection

The HTTP header X-XSS-Protection response header is a way to protect against XSS attacks that is supported by some browsers (Safari and Internet Explorer). Depending on the settings in the response header, different protection mechanisms are executed when an XSS attack is detected by the browser. For example, the protection mechanism can prevent the web application from loading or remove the insecure parts that contain the script for the XSS attack.

X-XSS-Protection: 0
X-XSS-Protection: 1
X-XSS-Protection: 1; mode=block

The 0 or 1 tells whether the protection filtering should be off or on (0 = off, 1 = on) and behind the semicolon is the information on how to act in case of an attempted injection. So in the case of the example with block, not only the injected script is removed (sanitized), but even the loading of the page is prevented.

Content Security Policy

An implemented Content Security Policy (CSP) adds another layer of security to a web application against injection attacks, including XSS. As mentioned earlier, the malicious scripts originate somewhere from a source that the attacker can access. Content Security Policy makes it possible to restrict the browser and thus the web application so that only scripts from sources that can be trusted are loaded. If the web application tries to load a script or something similar from a source that is not approved, it will be prevented by the browser. To enable CSP, the server running the web application must return the Content-Security-Policy HTTP header to the browser. So usually, a server administrator releases a set of domains or just the server’s one as a trusted source. For example, if you want only scripts from your own domain to be loaded, it looks like this:

Content-Security-Policy: default-src 'self'

Alternatively, this can also be set directly as an HTML meta-tag:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">

Encode, sanitize and escape data

In addition to the previously mentioned security aspects, separate programmatic protection mechanisms should also be implemented in the client and server. This means that the client and server evaluate what data comes in and in which form and whether it poses a threat or not. Consequently, evaluation and filtering mechanisms must be implemented for the incoming data. Since this is one of the most important protection mechanisms against XSS attacks, it will be explained in more detail.

Client-side XSS prevention

Most web applications are developed in JavaScript, which is why this is taken for the examples, but the principles behind the security mechanism are applicable to all programming languages and frameworks. A simple demonstration for an injected code could look like this:

/**
* Codepen: https://codepen.io/serquicky/pen/PobEXPv
*/
var elment = document.getElementById('elment');
var param = "Parameter";
elment.innerHTML = '<img src="unknown" onerror="alert(param)">';

In this example, the attacker exploits the fact, that the innerHTML call parses the passed statement. Now imagine that param is something that could be manipulated or passed by the attacker.

In order to be able to use innerHTML nevertheless, you can, for example, encode the passed parameter and thus practically sanitize it. After that, it will be treated as a string only. Here is an example of a possible implementation for sanitizing such parameters. The example is from the JavaScript toolkit The Vanilla JavaScript Toolkit.

/**
* Sanitize and encode all HTML in a user-submitted string
* Source: https://vanillajstoolkit.com/helpers/sanitizehtml/
* @param {String} str The user-submitted string
* @return {String} str The sanitized string
*/
var sanitizeHTML = function (str) {
return str.replace(/[^\w. ]/gi, function (c) {
return '&#' + c.charCodeAt(0) + ';';
});
};

If we then apply this function to our malicious string, we get the sanitized variant and it is interpreted accordingly only as a string.

&#60;img src&#61;&#34;unknown&#34; onerror&#61;&#34;alert&#40;param&#41;&#34;&#62;

In general, however, it is best not to write such functions yourself, but to use various libraries such as DOMPurify or js-xss, which have a variety of methods for different purposes. One advantage with such libraries is that they are usually up-to-date and you don’t have to worry about overlooking an attacker opportunity.

Server-side XSS prevention

As mentioned, on the server side you have the possibility to achieve certain security via the HTTP headers, but programmatic protection also makes sense. Using the example of WordPress and the programming language PHP, which is used for the development in WordPress, it makes sense to sanitize data and especially that comes from input fields. Because PHP is rendered on the server-side, the sanitization of the to-be-transferred data can take place before it is sent. WordPress offers a variety of sanitizing features on its own. For example, an input with a malicious script can be defused with the following function call:

$title = sanitize_text_field( $_POST['title'] );update_post_meta( $post->ID, 'title', $title );

However, this can also be done in the other direction, i.e. escaping or cleaning when displaying content in the client:

<?php echo esc_html( $title ); ?>

Especially when working with WordPress plugins, it is important to look into the sources of the respective plugins (if it is possible to do, mostly open-source), whether they take care to protect themselves from any code injection. Especially in plugins with many input and management options, it can quickly happen that an input field or an input option is overlooked. Overlooked sanitizing is not something unusual, even some of the biggest plugins overlooked this and got exploited, as was the instance with WooCommerce, for example.

How does Labler prevent XSS attacks?

In the current launch phase and in the development of our MVP we have developed rather little ourselves and rely more on existing plugins like Dokan and WooCommerce. For this reason, we have not taken any explicit programmatic security precautions against an XSS attack, because the plugins already provide this.

But what we strongly pay attention to, is that we always have the used plugins up-to-date. As with the previously mentioned example, there were security gaps in the past that were quickly closed again. For this reason, it is important to keep the plugins up to date. This means that as long as there is no plugin with a vulnerability, we also likely don’t have a vulnerability in our system.

However, as soon as we implement something new or extend it, we will use programmatic sanitization with the help of the WordPress functions mentioned above.

Conclusion

XSS attacks can be implemented quickly and easily by an attacker and can cause great damage. Taking precautions as a developer is very simple and effective as presented. It is important to put yourself in the position of the attacker and think about how you could proceed and close these vulnerabilities accordingly. Moreover, it is important to sensitize web developers to pay more attention to it, as this attack is still one of the most common ones and, as a result, many applications still do not take enough precautions.

Sources used for this article and which are good for more information and knowledge about Cross-site scripting attacks:

--

--