Cross-Site Scripting (XSS)

This module will teach you how to identify XSS vulnerabilities and exploit them.

XSS Basics

  • XSS vulnerabilities take advantage of a flaw in user input sanitization to "write" JavaScript code to the page and execute it on the client side, leading to several types of attacks.

  • XSS vulnerabilities are solely executed on the client-side and hence do not directly affect the back-end server.

  • XSS vulnerabilities can facilitate a wide range of attacks, which can be anything that can be executed through browser JavaScript code.

  • Example of Attacks:

    • A basic example of an XSS attack is having the target user unwittingly send their session cookie to the attacker's web server.

    • Another example is having the target's browser execute API calls that lead to a malicious action, like changing the user's password to a password of the attacker's choosing.

  • As XSS attacks execute JavaScript code within the browser, they are limited to the browser's JS engine (i.e., V8 in Chrome). They cannot execute system-wide JavaScript code to do something like system-level code execution. In modern browsers, they are also limited to the same domain of the vulnerable website.

  • XSS vulnerabilities may be found in almost all modern web applications and have been actively exploited for the past two decades.

  • XSS can be injected into any input in the HTML page, which is not exclusive to HTML input fields, but may also be in HTTP headers like the Cookie or User-Agent (i.e., when their values are displayed on the page).

Types of XSS

Stored (Persistent) XSS

  • This is the most critical type of XSS.

  • If our injected XSS payload gets stored in the back-end database and retrieved upon visiting the page, this means that our XSS attack is persistent and may affect any user that visits the page.

  • Stored XSS may not be easily removable, and the payload may need removing from the back-end database.

  • Many modern web applications utilize cross-domain IFrames to handle user input, so that even if the web form is vulnerable to XSS, it would not be a vulnerability on the main web application. This is why we are showing the value of window.origin in the alert box, instead of a static value like 1. In this case, the alert box would reveal the URL it is being executed on, and will confirm which form is the vulnerable one, in case an IFrame was being used.

  • Testing Payload: <script>alert(window.origin)</script>

  • To see whether the payload is persistent and stored on the back-end, we can refresh the page and see whether we get the alert again. If we do, we would see that we keep getting the alert even throughout page refreshes, confirming that this is indeed a Stored/Persistent XSS vulnerability. This is not unique to us, as any user who visits the page will trigger the XSS payload and get the same alert.

Reflected (Non-Persistent) XSS

  • Reflected XSS vulnerabilities occur when our input reaches the back-end server and gets returned to us without being filtered or sanitized.

  • If we visit the Reflected page again, the error message no longer appears, and our XSS payload is not executed, which means that this XSS vulnerability is indeed Non-Persistent.

  • Example:

    • Error Messages

    • Confirmation Messages

  • GET request sends their parameters and data as part of the URL. So, to target a user, we can send them a URL containing our payload.

DOM-Based XSS

  • While reflected XSS sends the input data to the back-end server through HTTP requests, DOM XSS is completely processed on the client-side through JavaScript.

  • DOM XSS occurs when JavaScript is used to change the page source through the Document Object Model (DOM).

  • There is an important concepts to understand, which is, the source and sink.

    • The Source is the JavaScript object that takes the user input, and it can be any input parameter like a URL parameter or an input field.

    • The Sink is the function that writes the user input to a DOM Object on the page.

  • Some of the commonly used JavaScript functions to write to DOM objects are:

    • document.write()

    • DOM.innerHTML

    • DOM.outerHTML

  • Some of the jQuery library functions that write to DOM objects are:

    • add()

    • after()

    • append()

  • If a Sink function writes the exact input without any sanitization (like the above functions), and no other means of sanitization were used, then we know that the page should be vulnerable to XSS.

XSS Discovery

Automated Discovery

  • Most Web Application Vulnerability Scanners (i.e. Burp, ZAP, and Nessus) can detect XSS vulnerabilities with its different types.

  • There are some other open-source tools specialized for XSS.

Manual Discovery

  • The most basic method of looking for XSS vulnerabilities is manually testing various XSS payloads against an input field in a given web page.

  • There are lists of XSS payloads like, PayloadBox and PayloadAllTheThings

  • Manually copying/pasting XSS payloads isn't the most efficient way as even if the application is vulnerable it would take a while to identify the right payload. Rather automating the process by having a script tryout the payloads and compare the response is a more efficient way.

Code Review

  • Code review is the most reliable method of detecting XSS vulnerabilities.

  • By reviewing the code and understanding how the system handles our input we can craft a payload for the system that we are confident that it's going to work.

XSS Attacks

Web Defacing

  • Defacing a website means changing its look for anyone who visits the website.

  • Such attacks can carry great media echo and may significantly affect a company's investments and share prices, especially for banks and technology firms.

  • Although many other vulnerabilities may be utilized to achieve the same thing, stored XSS vulnerabilities are among the most used vulnerabilities for doing so.

  • Three HTML elements are usually utilized to change the main look of a web page:

    • Background Color document.body.style.background

    • Background document.body.background

    • Page Title document.title

    • Page Text DOM.innerHTML

Phishing

  • Phishing attacks usually utilize legitimate-looking information to trick the victims into sending their sensitive information to the attacker.

  • A common form of XSS phishing attacks is through injecting fake login forms that send the login details to the attacker's server, which may then be used to log in on behalf of the victim and gain control over their account and sensitive information.

  • To perform an XSS phishing attack, we must inject an HTML code that displays a login form on the targeted page. This form should send the login information to a server we are listening on, such that once a user attempts to log in, we'd get their credentials.

  • To write HTML code to the vulnerable page, we can use the JavaScript function document.write()

  • To encourage the victim to use the login form, we should remove the content of the page, such that they may think that they have to log in to be able to use the page. To do so, we can use the JavaScript function document.getElementById().remove() function.

  • To find the id of the HTML element we want to remove, we can open the Page Inspector and then click on the element we need

  • a Netcat listener, will not handle the HTTP request correctly, and the victim would get an error, which may raise some suspicions. So, we can use a basic PHP script that logs the credentials from the HTTP request and then returns the victim to the original page without any injections. In this case, the victim may think that they successfully logged in and will use the website as intended.

Last updated