XSS can be more generally, although less excitingly, described as HTML injection. The more popular name belies the fact that successful attacks need not cross sites or domains and need not consist of JavaScript to be effective.
An XSS attack rewrites the structure of a Web page or executes arbitrary JavaScript within the victim's Web browser. This occurs when a Web site takes some piece of information from the user – an e-mail address, a user ID, a comment to a blog post, a zip code, and so on – and displays the information in a Web page. If the Web site is not careful, then the meaning of the HTML document can be disrupted by a carefully crafted string.
For example, consider the search function of an online store. Visitors to the site are expected to search for their favorite book, movie, or pastel-colored squid pillow, and if the item exists, they purchase it. If the visitor searches for DVD titles that contain living dead, the phrase might show up in several places in the HTML source. Here, it appears in a meta tag.
<SCRIPT LANGUAGE="JavaScript" SRC="/script/script.js"></SCRIPT>
<meta name="description" content="Cheap DVDs. Search results for living dead" />
<meta name="keywords" content="dvds,cheap,prices" /><title>
However, later the phrase may be displayed for the visitor at the top of the search results, and then near the bottom of the HTML inside a script element that creates an ad banner.
<div>matches for "<span id="ctl00_body_ctl00_lblSearchString"> living dead</span>"</div>
<script type="text/javascript"><!--
ggl_ad_client = "pub-6655321";
XSS comes in to play when the visitor can use characters normally reserved for HTML markup as part of the search query. Imagine if the visitor appends a double quote (“) to the phrase. Compare how the browser renders the results of the two different queries in each of the windows in Figure 1.1.
Note that the first result matched several titles in the site's database, but the second search reported “No matches found” and displayed some guesses for a close match. This happened because living dead” (with quote) was included in the database query and no titles existed that ended with a quote. Examining the HTML source of the response confirms that the quote was preserved:
<div>matches for "<span id="ctl00_body_ctl00_lblSearchString"> living dead"</span>"</div>
If the Web site will echo anything we type in the search box, what might happen if a more complicated phrase were used? Figure 1.2 shows what happens when JavaScript is entered directly into the search.
By breaking down the search phrase, we see how the page was rewritten to convey a very different message to the Web browser than the Web site's developers intended. The HTML language is a set of grammar and syntax rules that inform the browser how to interpret pieces of the page. The rendered page is referred to as the Document Object Model (DOM). The use of quotes and angle brackets enabled the attacker to change the page's grammar to add a JavaScript element with code that launched a pop-up window. This happened because the phrase was placed directly in line with the rest of the HTML content.
<div>matches for "<span id="ctl00_body_ctl00_lblSearchString"> living dead<script>alert("They're coming to get you, Barbara.") </script></span>"</div>
Instead of displaying <script>alert… as text like it does for the words living dead, the browser sees the <script> tag as the beginning of a code block and renders it as such. Consequently, the attacker is able to arbitrarily change the content of the Web page by manipulating the DOM.
Before we delve too deeply into what an attack might look like, let's see what happens to the phrase when it appears in the meta tag and ad banner. Here is the meta tag when the phrase living dead” is used:
<meta name="description" content="Cheap DVDs. Search results for living dead"" />
The quote character has been rewritten to its HTML-encoded version – " – which browsers know to display as the “ symbol. This encoding preserves the syntax of the meta tag and the DOM in general. Otherwise, the syntax of the meta tag would have been slightly different:
<meta name="description" content="Cheap DVDs. Search results for living dead"" />
This lands an innocuous pair of quotes inside the element and most browsers will be able to recover from the apparent typo. On the other hand, if the search phrase is echoed verbatim in the meta element's content attribute, then the attacker has a delivery point for an XSS payload:
<meta name="description" content="Cheap DVDs. Search results for living dead"/>
<script>alert("They're coming to get you, Barbara.")</script>
Here's a more clearly annotated version of the XSS payload. Note how the syntax and grammar of the HTML page have been changed. The first meta element is properly closed, a script element follows, and a second meta element is added to maintain the validity of the HTML.
<meta name="description" content="Cheap DVDs. Search results for living dead"/> close content attribute with a quote, close the meta element with />
<script>…</script> add some arbitrary JavaScript
<meta name=" create an empty meta element to prevent the browser from displaying the dangling "/> from the original <meta description… element
The ggl_hints parameter in the ad banner script element can be similarly manipulated. Yet, in this case, the payload already appears inside a script element, so the attacker needs only to insert valid JavaScript code to exploit the Web site. No new elements needed to be added to the DOM for this attack. Even if the developers had been savvy enough to blacklist <script> tags or any element with angle brackets, the attack would have still succeeded.
<script type="text/javascript"><!--
ggl_ad_client = "pub-6655321";
ggl_hints = "living dead"; close the ggl_hints string with";
ggl_ad_client="pub-attacker"; override the ad_client to give the attacker credit
function nefarious() { } perhaps add some other function
foo=" create a dummy variable to catch the final ";
Each of the previous examples demonstrated an important aspect of XSS attacks: the location on the page where the payload is echoed influences what characters are necessary to implement the attack. In some cases, new elements can be created, such as <script> or <iframe>. In other cases, an element's attribute might be modified. If the payload shows up within a JavaScript variable, then the payload need only consist of code.
Pop-up windows are a trite example of XSS. More vicious payloads have been demonstrated to
Regardless of what the actual payload is trying to accomplish, all forms of the XSS attack rely on the ability of a user-supplied bit of information to be rendered in the site's Web page such that the DOM structure will be modified. Keep in mind that changing the HTML means that the Web site is merely the penultimate victim of the attack. The Web site acts as a broker that carries the payload from the attacker to the Web browser of anyone who visits it.
Alas, this chapter is far too brief to provide a detailed investigation of all XSS attack techniques. One in particular deserves mention among the focus on inserting JavaScript code and creating HTML elements, but is addressed here only briefly: Cascading Style Sheets (CSS). Cascading Style Sheets, abbreviated CSS and not to be confused with this attack's abbreviation, control the layout of a Web site for various media. A Web page could be resized or modified depending on whether it's being rendered in a browser, a mobile phone, or sent to a printer. Clever use of CSS can attain much of the same outcomes as a JavaScript-based attack. In 2006, MySpace suffered a CSS-based attack that tricked victims into divulging their passwords (www.caughq.org/advisories/CAU-2006-0001.txt). Other detailed examples can be found at http://p42.us/css/.