XSS vulnerabilities are into three distinct types:
- Reflected - This occurs when a malicious payload is injected into a user-controlled input or parameter as part of the victim's request, which is then rendered within an application response.
- Stored - This occurs when user-controlled input is rendered within a response in a persistent way, meaning that it will continue to execute until the injected code is removed. When this happens, the payload is usually stored within the application database and returned automatically on a page where the payload is meant to be displayed.
Medium - High
Medium - Critical
Cross-Site Scripting is relatively simple to fuzz for and identify. The probability is ranked highly for this reason. While serious, exploitation of a Reflected XSS has much less significant consequence than a Stored or DOM-Based XSS. It is for this reason the Impact category ranges from Medium to Critical.
There are three (3) categories under which XSS attacks currently fall: Reflected, Stored, and DOM-Based. The categories depend on how the attacker supplies malicious input and whether or not that payload remains embedded in the vulnerable application after the attack. Reflected and Stored XSS attacks are also referred to as Server Side XSS, while DOM-Based XSS is sometimes referred to as Client Side XSS. The screenshots from the following examples were created using the Damn Vulnerable Web Application on a NAT networked group of Virtual Machines.
script tags to be injected directly into the web application. Take the following form:
The above input is sent to the server and a new page is rendered containing the user's input. If, instead, a
alert, the application can be manipulated:
Different from reflected XSS, stored cross-site scripting occurs when malicious input persists on a database that victims repeatedly interact with. After the payload is submitted by the attacker and stored on the server, any user who accesses the infected resource will also execute the payload. Look at the comment section below:
The above payload will execute and reveal the domain of the web application in an alert as follows:
In addition to seeing the payload execute as the attacker, any user who browses to this comment section will see the alert as well. This is because the payload is stored on the server and gets rendered every time the resource is called. This is an incredibly effective way for an attacker to potentially hijack multiple users sessions and perform actions such as gathering credentials from various accounts on a vulnerable application.
DOM-Based XSS is often misunderstood, as the attack vector is different from Stored or Reflected XSS. DOM-Based XSS is a client side injection where the XSS payload is injected into a function which then updates the page being viewed by the victim. On the webpage below, there is a user controlled parameter that allows an end user to select the language of the page. When a new language is selected from the dropdown, the parameter in the URL changes:
Instead of selecting the options from the dropdown, the attacker can try to modify the DOM directly and inject a payload:
Going Beyond the Popup
localStorage or session storage, redirecting the victim to another location, exploiting vulnerabilities within the victim's browser, or interacting with the victim to prompt for credentials or other potentially sensitive information.
BROWSERHOOK cookie is added to the established session and a communication channel has been established via the execution of the hooking code:
On the attacker's system, the hooked browser shows up on the BeEF dashboard, indicating that the attacker can interact with the hooked victim:
HTTPOnly flag. The results from this request are shown in the module command results:
The attacker can perform other actions, like prompt the victim for their system credentials as a way to collect potentially sensitive information that could be used in other attacks. The image below shows a BeEF "Pretty Theft" module which is styled to look like a Windows credential prompt:
When the attacker sends the credential prompt to the victim, the victim's browser window will display the prompt, instructing the victim to enter their local system credentials to dismiss the window and continue using their browser:
Any information submitted by the victim is returned to the attacker, as shown below:
This shows only a few ways in which cross-site scripting vulnerabilities can be leveraged by an attacker within a web application. Depending on the intended use of the application, an XSS vulenrability can allow an attacker to perform numerous actions against any users who are targeted directly or indirectly by these attacks.
Cross-site scripting can be effectively prevented by sanitizing all user input. Ensuring that all user-controlled variables are subjected to input validation greatly decreases the chance of compromise. Preventing DOM-Based XSS requires the structure of the application be assessed in its entirety and is thus more complex. Tips for preventing DOM-Based XSS can be implemented as a result of a source code review. See references for a guide on conducting application source code reviews.
Many modern web libraries have built-in protections to automatically render data in a sanitized way. One common tactic is to replace characters required for XSS with their Unicode equivalent. For example, the left angle bracket required for a
<script> tag could be rendered as Unicode character
U+2329, appearing the same to a user but not rendering as a valid HTML character.
Additional protections can be implemented and layered as part of a defense-in-depth strategy. These protections include the addition of HTTP response headers such as a
Content-Security-Policy which can restrict the origins from which scripts can be loaded or be configured to define specific criteria that must be met to allow for script execution.