XSS (cross-site scripting)- explained in layman's term
In this blog, you will learn
- What is XSS?
- How does XSS works?
- What are the types of XSS?
- How to find and test for XSS?
- Impact of XSS
- How to prevent XSS attacks?
- References
What is XSS?
Cross-site scripting (also commonly known as XSS) is a web application vulnerability that allows an attacker to compromise the interaction that users have with a vulnerable web application. It allows attackers to bypass the security measures put in by the developers to avoid the XSS attack.
XSS vulnerabilities enable malicious actors( or attackers) to inject malicious code (client-side scripts) into web pages viewed by users. Once executed on the user’s browser, this code could then perform actions such as changing the behavior or appearance of the website, stealing sensitive data, performing actions on behalf of the user, and more.
The root cause of XSS vulnerability arises from the failure to properly validate user input before processing, allowing the client-side script (commonly JavaScript) to be injected in a manner that will enable it to execute. Therefore, your application is at risk of XSS vulnerability wherever it handles user input.
How does XSS works?
Cross-site scripting works by manipulating a vulnerable website so that it returns malicious JavaScript to users. When the malicious code executes inside a victim’s browser, the attacker can fully compromise their interaction with the application.
When a web application is vulnerable to this type of attack, it will pass unvalidated input; sent through requests, back to the client(or user). The common methodology of the attack includes a design step in which the attacker creates and tests the malicious URL, a social engineering step in which the attacker convinces the victims to load the URL on their browsers, and then the execution of the malicious code using the victim’s browser.
Commonly the attacker’s code is written in the JavaScript language, but other scripting languages are also used, e.g., ActionScript, VBScript, and XSS. Attackers typically leverage these vulnerabilities to install key loggers, steal victim cookies, perform clipboard theft, and change the content of the page (e.g., download links).
What are the types of XSS?
There are three main types of XSS attacks. These are:
- Reflected XSS
- Stored XSS
- DOM-based XSS
Reflected cross-site scripting
Non-persistent (reflected) XSS is the most common type of cross-site scripting. Just as the name implies, reflected XSS occurs when the injected malicious script results show up or are immediately reflected by the user without adequately sanitizing the content.
Here is a simple example of a reflected XSS vulnerability:
URL: https://insecure-website.com/status?message=All+is+well.
Response: <p>Status: All is well.</p>
The application doesn’t perform any other processing of the data, so an attacker can easily construct an attack like this:
URL: https://insecure-website.com/status?message=<script>/*+Bad+stuff+here...+*/</script>
Response: <p>Status: <script>/* Bad stuff here… */</script></p>
If the user visits the URL constructed by the attacker, then the attacker’s script executes in the user’s browser, in the context of that user’s session with the application. At that point, the script can carry out any action, and retrieve any data, to which the user has access.
Stored cross-site scripting
Stored XSS is also known as persistent or second-order XSS. This is a more devastating variant of a cross-site scripting flaw. It occurs when the data provided by the attacker is saved by the server at the database and then permanently displayed on “normal” pages to the other users in the course of regular browsing, without proper HTML escaping.
The data in question might be submitted to the application via HTTP requests; for example, comments on a blog post, user nicknames in a chat room, or user details on a user profile. In other cases, the data might arrive from other untrusted sources; for example, a webmail application displaying messages received over SMTP, or a marketing application displaying social media posts.
Here is a simple example of a stored XSS vulnerability. A message board application lets users submit messages, which are displayed to other users:
<p>Hello, this is my message!</p>
The application doesn’t perform any other processing or sanitizing of the data before displaying it to the user, so an attacker can easily send a message that attacks other users:
<p><script>/* Bad stuff here… */</script></p>
DOM cross-site scripting
DOM XSS occurs when the injected malicious code does not get to the web server. Instead, it is reflected by client-side JavaScript code on the client-side.
DOM-based XSS vulnerabilities usually arise when JavaScript takes data from an attacker-controllable source, such as the URL, and passes it to a sink that supports dynamic code execution, such as eval() or innerHTML. This enables attackers to execute malicious JavaScript, which typically allows them to hijack other users’ accounts.
To deliver a DOM-based XSS attack, you need to place data into a source so that it is propagated to a sink and causes the execution of arbitrary JavaScript.
In the following example, an application uses some JavaScript to read the value from an input field and write that value to an element within the HTML:
var search = document.getElementById(‘search’).value;
var results = document.getElementById(‘results’);
results.innerHTML = ‘You searched for: ‘ + search;
If the attacker can control the value of the input field, they can easily construct a malicious value that causes their own script to execute:
You searched for: <img src=1 onerror=’/* Bad stuff here… */’>
In a typical case, the input field would be populated from part of the HTTP request, such as a URL query string parameter, allowing the attacker to deliver an attack using a malicious URL, in the same manner as reflected XSS.
To summarize all three types;
Reflected XSS, where the malicious script comes from the current HTTP request.
Stored XSS, where the malicious script comes from the website’s database.
DOM-based XSS, where the vulnerability exists in client-side code rather than server-side code.
How to find and test for XSS?
There are many process for finding and testing XSS but the most grounded method (according to me) is manual testing and the best way to do manual testing is reviewing/ understanding the code, So in this blog we will be looking at the manual testing for reflected, stored and Dom based XSS.
Manually testing for reflected and stored XSS normally involves submitting some simple unique input (such as a short alphanumeric string) into every entry point in the application, identifying every location where the submitted input is returned in HTTP responses, and testing each location individually to determine whether suitably crafted input can be used to execute arbitrary JavaScript. In this way, you can determine the context in which the XSS occurs and select a suitable payload to exploit it.
Manually testing for DOM-based XSS arising from URL parameters involves a similar process; placing some simple unique input in the parameter, using the browser’s developer tools to search the DOM for this input, and testing each location to determine whether it is exploitable. However, other types of DOM XSS are harder to detect. To find DOM-based vulnerabilities in non-URL-based input (such as document.cookie) or non-HTML-based sinks (like setTimeout), there is no substitute for reviewing JavaScript code.
(Refer this to find more about sinks)
You can refer this to know more about Reflected XSS testing and this for practicing.
You can refer this to know more about Stored XSS testing and this for practicing.
You can refer this to know more about Dom XSS testing and this for practicing.
Impact of XSS
The actual impact of an XSS attack generally depends on the nature of the application, its functionality, how it process it’s data, and the status of the compromised user. For example:
- In an application where all users are anonymous and all information is public, the impact will often be minimal.
- In an application holding sensitive data, such as banking transactions, emails, or healthcare records, the impact will usually be serious.
- If the compromised user has elevated privileges within the application and gained the admin or root access, then the impact will generally be critical, allowing the attacker to take full control of the vulnerable application and compromise all users and their data.
If successful, a cross site scripting attack can severely impact websites and web applications, damage their reputation and relationships with customers. XXS can deface websites, can result in compromised user accounts, and can run malicious code on web pages, which can lead to a compromise of the user’s device.
The consequence of an XSS attack is the same regardless of whether it is reflected, stored or DOM Based. The difference is in how the payload arrives/ processed at the server. Do not be fooled into thinking that a “read-only” or “brochure ware” site is not vulnerable to serious reflected XSS attacks. XSS can cause a variety of problems for the end user that range in severity from an annoyance to complete account compromise.
The most severe XSS attacks involve disclosure of the user’s session cookie, allowing an attacker to hijack the user’s session and take over the account. Other damaging attacks include the disclosure of end user files, installation of Trojan horse programs or keyloggers, redirecting the user to some other page or site, or modifying presentation of content and even do a phishing attack. An XSS vulnerability on a pharmaceutical site could allow an attacker to modify dosage information resulting in an overdose, this is just an example and the outcomes are infinite and can be more evil and severe.
How to prevent XSS attacks?
Preventing cross-site scripting is trivial in some cases but can be much harder depending on the complexity of the application and the ways it handles user-controllable data.
Commonly used main prevention methods include:
- Data validation
- Filtering
- Escaping
The first step in the prevention of this attack is Input/Data validation. Everything, that is entered by the user should be precisely validated. Data validation can be named as the basis for ensuring the system’s security. I would remind, you that the idea of validation is not to allow inappropriate input.
Therefore it just helps to reduce the risks, but may not be enough to prevent the possible XSS vulnerability.
Another good prevention method is user input filtering. The idea of the filtering is to search for risky keywords in the user’s input and remove them or replace them with empty strings.
Those keywords may be:
- <script></script> tags
- JavaScript commands
- HTML markup
- URL encoded JavaScript or HTML
Input filtering is quite easy to practice. It can be performed in different ways too.
Like:
- By developers who have written server-side code.
- An appropriate programming language library is being used.
In this case, some developers write their own code to search for appropriate keywords and remove them. However, the easier way would be to select an appropriate programming languages library to filter the user’s input.
Another possible prevention method is characters escaping. In this practice, appropriate characters are being changed by special codes. For Example, ‘<’ escaped character may look like ‘<’. It is important to know, that we can find appropriate libraries to escape the characters.
Meanwhile, good testing should not be forgotten as well. It should be invested in good software testers’ knowledge and reliable software testing tools. This way good software quality will be better assured.