Google

Quotes and XSS — Planning Your Escape

Written on:April 3, 2013
Comments are closed

Introduction

It’s been my observation that when it comes to XSS prevention, angle brackets associated with HTML and script tags (<>) often get the majority of the attention. While eliminating script tags as a potential XSS vector is a great start, just as important, and seemingly most forgotten when it comes to input validation and output encoding, are double (“) and single (‘) quotes. Whether they are completely ignored or improperly escaped, they seem to be a frequent cause of reflected XSS. Because I come across this issue so often, both during application pen tests as well as everyday Internet browsing, I wanted to dedicate a post to the dangers of quotes and XSS.

Discussion

Why is failure to safely handle user-submitted quotes such a bad thing?  Quite simply, if that input is incorporated into the server response without proper input validation and output encoding, it could allow for the direct modification of HTML attributes. To demonstrate, I’ll start with the more obvious <input> tag and then move on to some other examples where I commonly find reflected XSS resulting from insecurely handled quotes.

Input Tags

Let’s take a look at a simple but common example of a webpage with a search function. In this example, when the user clicks Search their search term is returned in the input box of the response page.

XSS-vulnerable site

The HTML for the search function on this page might look like this:

Search for a product on our site:

Unfortunately, this site does not strip, escape, or encode quotes included in a search term. Should the user submit a quoted, compound search term such as “desk chair”, the HTML returned in the response page would now look like this:

Search for a product on our site:

What has happened here is we have escaped the value attribute and created another attribute called desk. Of course in HTML parlance, this new attribute means nothing; however, using this approach we can insert valid attributes which can result in successful XSS exploits. Let’s use the common onmouseover attribute to execute a user-driven XSS exploit with the following search term:
” onmouseover=”alert(‘XSS’)

The HTML of the response page would now look like this:

Search for a product on our site:

This search term modifies the resulting HTML so that it executes the XSS should the user mouse over the input field. Aside from the more obvious <input> tag, sites often incorporate user input directly into some less noticeable, but equally injectable locations of the returned HTML of the server’s response. These include drop-down menus, hyperlinks, meta tags, 3rd party advertisements, and even directly into HTML-embedded JavaScript. Lets’ take a closer look at some examples:

Drop-down Menus

Sites often use drop-down menus (<select> tags) as a means for users to sort or filter search results (by price, popularity, etc). Sometimes when the user selects an option from one of these menus, they are executing additional searches that incorporate their original search term along with some other parameters that serve to sort or filter the results. For example, selecting a drop down item to sort search results by popularity might append the parameter ?sort=popular to the original query and re-execute the search.

The response HTML for the drop-down menu in our previous “Products A-Z” example page (which sorts results by price) might look like the following:

Sort by:

In this case, selecting either option would execute the reflected XSS from the original search term.

Hyperlinks

Sites might also incorporate user input into customized hyperlinks within the returned HTML of a sever response. Some examples I’ve come across several times are page navigation and “results per page” links. Once again, using our previous “Products A-Z” example page, the HTML of the “Results per page” links might look like the following:

Results per page:

  • 25
  • 50
  • 100
  • Hovering the mouse over any of these links would also execute the reflected XSS.

    xsshyperlinks

    Take notice of the URL preview in the lower left corner of the above screenshot. Specifically, note how the URL unexpectedly terminates after the ?keywords=” due to the double quote included in our search term. Seeing this behavior while navigating a site is a tell-tale sign that it does not properly handle quotes and may be vulnerable to reflected XSS.

    Meta Tags

    Often overlooked, <meta> tags are another fairly common source of reflected XSS attacks because they include unvalidated, unencoded user inputs. For example, a site might use the following page description meta tag for Search Engine Optimization:

    These tend to be overlooked because the meta tag itself is not visibly displayed to the screen. Even so, meta tags have attributes that make it possible to execute XSS attacks without the need for user interaction and even support encoded data which may help to evade rudimentary input validation filters.

    Here’s an example <meta> tag that places a user’s search term in the content attribute without proper encoding.

    One of the other attributes of the <meta> tag is http-equiv which, when populated with possible value of “refresh”, will refresh the page using the value in the “content” attribute. Further, we can base64 encode the XSS injection (in this case: <script>alert(‘XSS’)</script>)and insert that into the “content” attribute, which in turn, will execute it within the browser automatically. In this example, our XSS input would look like this:

    a;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4″ HTTP-EQUIV=”refresh”

    This creates the following meta tag in the returned HTML:

    Here’s an alternate, non-encoded version that works in Chrome:

    Sometimes, rudimentary input validation or output escaping prevents the execution of a script in the meta tag. Instead of attempting to embed the script in the returned HTML, you might also consider testing a redirect to an external, vulnerable page.

    For example, I’ve noticed sites that attempt to escape double quotes by inserting a backslash (\) in front of each one (ineffective in prevention of XSS within HTML attributes). In our example above, this additional character renders the base64 injection string ineffective. Instead, we can insert the URL of a “malicious” site under our control (containing drive-by-download, XSS, etc), making the value of the content attribute: content=”a;url=hxxp://malicious.com”

    Note: If the site your are testing does injection escape characters and the URL to which you are attempting to redirect cannot be terminated with a backslash, insert a hash symbol (#) to create an artificial URL fragment that won’t be processed server-side. Also, because the quotes in the HTTP-EQUIV value are optional, they can be omitted altogether to avoid any additional unwanted backslashes. With that, our injection input would become: “a;url=hxxp://malicious.com#” HTTP-EQUIV=refresh which creates the following meta tag:

    Once the page loads, the meta tag will execute and the user will be automatically redirected to the malicious site.

    3rd Party Advertisements

    3rd party ads are another source of quote-based reflected XSS that I’ve come across. Even sites that do a good job of validating and encoding user input everywhere else seem to have a hard time with 3rd party advertisements and I suspect it’s because they might be copying/pasting the 3rd party ad code directly in their site’s HTML. Here’s a generalized example that I’ve seen on a popular website:

    Sorry, the comment form is closed at this time.