What is cross-site scripting (XSS)?
How XSS exploits work and how to defend against them
Cross-site scripting (XSS) is a security flaw in web applications and websites that allows cyber attackers to inject malicious code that can interfere with a user’s web experience, lift sensitive data, and otherwise interact with the web service as if they were the victim user.
It involves placing malicious scripts into the back-end of a website so that when a user visits it, malicious code is then executed on their machine to achieve whatever the hacker wants with the attack. Because the attacker’s script was injected into the otherwise trusted website, the victim’s browser will accept it and run whatever it’s told, as it will seem the instructions came from a reliable service.
Exploitation of XSS vulnerabilities has been prevalent since its moniker was first coined in January 2000 by Microsoft’s security engineers. According to Microsoft, XSS was just one of many names for the vulnerability it was considering at the time. Others included 'unauthorised site scripting', 'URL parameter script injection', and 'synthesised scripting', among others.
Twenty-two years on, it’s still among the most-exploited internet vulnerabilities in 2022. A recent report from cloud company Akamai revealed that XSS was still among the three most-exploited security vulnerabilities in 2022. Used in attacks on organisations in nearly all sectors, its findings showed companies offering business services were attacked the most using XSS injections.
XSS attacks are still dangerous in today’s threat landscape, which is often dominated by stories of ransomware, malware, distributed denial of service (DDoS), and other threats. There are also different types of XSS attacks - two were identified early on and the third main method was discovered five years after its initial discovery.
How does XSS work?
The vulnerability allows attackers to bypass the Same Origin Policy (SOP) - a basic principle of web design that prevents applications from accessing the content on pages from a different origin. Typically, the policy ensures websites operate with guardrails, stopping code from that one random online marketplace you visited from accessing code on your online banking dashboard.
For example, under SOP, https://www.itpro.com/index.html can access scripts from the same root address, such as https://www.itpro.com/example.html, but not from https://www.facebook.com/example.html.
Get the ITPro. daily newsletter
Receive our latest news, industry updates, featured resources and more. Sign up today to receive our FREE report on AI cyber crime & security - newly updated for 2024.
However, hackers are able to bypass this restriction by using a cross-site scripting vulnerability to inject their own code onto a website, making it look like that malicious code originated from the attacked website, rather than an external source.
Importantly, this vulnerability only exists on sites that present unsanitised user information as an output on their pages. This is effectively any site that hosts and stores comments, posts, form entries or any other method of user input, without performing any additional processing steps before it's hosted, such as stripping away HTML code.
A visitor's browser will treat the malicious code on the site's page as legitimate source code and execute the script automatically, although the exact method of execution can vary depending on the style of attack.
The majority of attacks tend to use JavaScript to execute code in a victim's browser, however other languages such as Java, Flash and Ajax are also sometimes used.
What is the impact of a successful XSS exploit?
Targeting users
Cookie theft has become the most common way of exploiting XSS, especially as the vulnerability gives hackers access to session tokens. Once these are copied over from a victim's browser to their own, a hacker can impersonate the user to perform actions on their behalf, including accessing any sensitive data associated with an online account, or altering credentials to take over the account entirely.
If the affected user has elevated privileges, such as admin rights to a website, the hacker could even launch additional attacks on the server itself, as was the case with the XSS and brute force attacks on Apache.org infrastructure in 2010.
However, this is all dependent on the user being logged into their account at the time of the cookie theft and will not work if other authentication steps are required to maintain access, such as a machine's IP address.
As browsers and user habits have developed, new opportunities for theft have also arisen. Modern browsers now make use of HTML5, something that malicious JavaScript can also exploit to gain access to additional data such as files stored on a user's system or even their webcam. It's also possible to use an XSS vulnerability to target a user's passwords, although this is only possible with users that have password managers that autofill data into online forms.
This is all in addition to a hacker being able to view and record data associated with a user's account, including financial data and highly sensitive personal information.
Targeting websites
Given that XSS exploits could allow a hacker to gain access to admin accounts, some attacks will target the website itself.
In 2018, a hacker pleaded guilty to two counts of computer fraud following a three-year hacking spree of US government and military websites. In that instance, Billy Ribeiro Anderson admitted to exploiting XSS vulnerabilities to gain admin privileges, only to then deface the websites with political messages.
What are the types of XSS attacks?
Although we've covered the general idea behind a cross-site scripting attack, there are a number of different methods that an attacker can use to exploit the vulnerability.
These are:
- Reflected XSS
- Stored XSS
- DOM-based XSS
Reflected XSS
Reflected XSS is by far the simplest and most common method used.
With this type of XSS attack, the hacker must deliver their payload to a victim manually though a crafted URL containing malicious code. Typically spread through phishing scams, users are encouraged to click a link which will then send a malicious HTML request to a web server, which then reflects this back onto the user's browser, where it's executed.
This same style was used in a string of attacks on eBay in 2014, when hackers used the platform to post fake product listings which included links to fake websites. These URLs were laden with malicious code that executed on a victim's browser when they tried to access the external site. In that instance, the attack placed the user's eBay account at risk, including any saved card details and personal information.
This attack is notably easier to perform than other types of XSS attack, as the payload doesn't need to be stored on the target site's database, where it could be discovered and removed. However, greater awareness of phishing scams and more robust in-built browser protections have made this harder to perform in recent times.
Stored XSS
Sometimes called persistent XSS, this style of attack involves tricking a website into storing malicious HTML requests on its database, which can then infect any user requesting access to that server.
To explain, let's consider the following example:
Imagine you're accessing a website that allows users to sell their used clothes. Visitors are able to create accounts and then make a new listing by sending a request to the site's server. The user inputs the name of the item, the price, and a brief description of the quality of the clothing into an online form. This request is then sent to the website's server, where the information is stored and listed for others to see.
Now imagine a hacker discovers this website, and begins to probe for weaknesses by following the same steps above, only they notice that the submission form provides the option to customise the text using HTML code. Instead of providing a description for an item of clothing, they instead place a piece of custom JavaScript, which is then sent to the website's server, and stored for others to access.
If this happens, an innocent user may arrive at the website and request to view the list of items for sale, but instead finds the list put there by the hacker. Once this new user clicks on the description, the script will be secretly executed on whichever web browser they are using.
This is a particularly dangerous attack style as it can deploy and spread to any user that enters the website, and does not require a lot of effort on the hacker's part.
DOM-based XSS
With the development of ever more sophisticated websites, it's become more difficult to initiate reflected and stored XSS attacks. This has given rise to the DOM-based XSS attack, which, instead of relying on server-side vulnerabilities, triggers malicious scripts inside a user's browser instead of the site server.
This type of attack relies on websites that write data to the user's document object model (DOM) without sanitising that data first. Hackers are able to inject malicious HTML script into a legitimate URL, which can then be sent to a user, much in the same way as a reflected XSS attack. However, rather than sending the script to the website's server once a URL is clicked, the attack waits for a static version of a page to be returned from the server, at which point the user's browser begins to build the DOM of the page. It's at this point that the browser locates the script and runs it.
With DOM-based XSS attacks, the script never reaches the site's server, and therefore is immune to any server-side XSS detection tools.
How to defend against cross-site scripting attacks
In many cases, XSS attacks can be defended against by ensuring you maintain thorough data sanitisation across a website. Any and all data that is submitted by a user should be scrutinised by a robust filtering process, including finding out what data is expected for each field or whether it's valid. This will help to make sure the data does not have any markers that could transform it into executable code.
Furthermore, it is necessary to enforce output encoding on the website. To achieve this, it is possible to encode HTML tags that would usually mark the start or end of an executable script. An example of this is < or > as well as punctuation marks or parentheses. These can all be encoded so that the browser refrains from executing them but instead prints them.
Another good place to start is by enacting stronger policies like only accepting links with whitelisted protocols ( for example https://).
Lastly, if you're interested in finding out more and visually seeing an XSS exploit in action, or for those developers who need to better understand how to code against these weaknesses, take a look at this handy simulation game developed by Google. All you need to get started is some knowledge of JavaScript and Python before you can dive into its six levels of varying difficulty.
Dale Walker is a contributor specializing in cybersecurity, data protection, and IT regulations. He was the former managing editor at ITPro, as well as its sibling sites CloudPro and ChannelPro. He spent a number of years reporting for ITPro from numerous domestic and international events, including IBM, Red Hat, Google, and has been a regular reporter for Microsoft's various yearly showcases, including Ignite.