Cross-site scripting: Difference between revisions
m more quoting->entity encoding clarifications |
|||
Line 19: | Line 19: | ||
===Type 0=== |
===Type 0=== |
||
This form of XSS vulnerability has been referred to as '''DOM-based''' or '''Local''' cross-site scripting, and while it isn't new by any means, a recent paper ([http://www.webappsec.org/projects/articles/071105.shtml DOM-Based cross-site scripting]) does a good job of defining its characteristics. With Type 0 cross-site scripting vulnerabilities, the problem exists within a page's client-side script itself. For instance, if a piece of JavaScript accesses a URL request parameter and uses this information to write some HTML to its own page, and this information |
This form of XSS vulnerability has been referred to as '''DOM-based''' or '''Local''' cross-site scripting, and while it isn't new by any means, a recent paper ([http://www.webappsec.org/projects/articles/071105.shtml DOM-Based cross-site scripting]) does a good job of defining its characteristics. With Type 0 cross-site scripting vulnerabilities, the problem exists within a page's client-side script itself. For instance, if a piece of JavaScript accesses a URL request parameter and uses this information to write some HTML to its own page, and this information is not encoded using HTML entities, a XSS hole will likely be present, since this written data will be re-interpreted by browsers as HTML which could include additional client-side script. |
||
In practice, exploiting such a hole would be very similar to the exploit of Type 1 vulnerabilities (see below), except in one very important situation. Because of the way [[Internet Explorer]] treats client-side script in objects located in the "local zone" (for instance, on the client's local hard drive), a XSS hole of this kind in a local page can result in remote execution vulnerabilities. For example, if an attacker hosts a malicious website, which contains a link to a vulnerable page on a client's local system, a script could be injected and would run with privileges of that user's browser on their system. This bypasses the entire client-side sandbox, not just the cross-domain restrictions that are normally bypassed with XSS exploits. |
In practice, exploiting such a hole would be very similar to the exploit of Type 1 vulnerabilities (see below), except in one very important situation. Because of the way [[Internet Explorer]] treats client-side script in objects located in the "local zone" (for instance, on the client's local hard drive), a XSS hole of this kind in a local page can result in remote execution vulnerabilities. For example, if an attacker hosts a malicious website, which contains a link to a vulnerable page on a client's local system, a script could be injected and would run with privileges of that user's browser on their system. This bypasses the entire client-side sandbox, not just the cross-domain restrictions that are normally bypassed with XSS exploits. |
||
Line 25: | Line 25: | ||
===Type 1=== |
===Type 1=== |
||
This kind of cross-site scripting hole is also referred to as a '''non-persistent''' or '''reflected''' vulnerability, and is by far the most common type. |
This kind of cross-site scripting hole is also referred to as a '''non-persistent''' or '''reflected''' vulnerability, and is by far the most common type. |
||
These holes show up when data provided by a web client is used immediately by server-side scripts to generate a page of results for that user. If unvalidated user supplied data is included in the resulting page without HTML |
These holes show up when data provided by a web client is used immediately by server-side scripts to generate a page of results for that user. If unvalidated user supplied data is included in the resulting page without HTML encoding, this will allow client-side code to be injected into the dynamic page. A classic example of this is in site search engines: if one searches for a string which includes some HTML special characters, often the search string will be redisplayed on the result page to indicate what was searched for, or will at least include the search terms in the text box for easier editing. If all occurrences of the search terms aren't HTML entity encoded, an XSS hole will result. |
||
At first blush, this doesn't appear to be a serious problem since users can only inject code into their own pages. However, with a small amount of [[social engineering (computer security)|social engineering]], an attacker could convince a user to follow a malicious URL which injects code into the results page, giving the attacker full access to that page's content. Due to the general requirement of the use of some social engineering in this case (and normally in Type 0 vulnerabilities as well), many programmers have disregarded these holes as not terribly important. This misconception is sometimes applied to XSS holes in general (even though this is only one type of XSS) and there is often disagreement in the security community as to the importance of cross-site scripting vulnerabilities. |
At first blush, this doesn't appear to be a serious problem since users can only inject code into their own pages. However, with a small amount of [[social engineering (computer security)|social engineering]], an attacker could convince a user to follow a malicious URL which injects code into the results page, giving the attacker full access to that page's content. Due to the general requirement of the use of some social engineering in this case (and normally in Type 0 vulnerabilities as well), many programmers have disregarded these holes as not terribly important. This misconception is sometimes applied to XSS holes in general (even though this is only one type of XSS) and there is often disagreement in the security community as to the importance of cross-site scripting vulnerabilities. |
||
===Type 2=== |
===Type 2=== |
||
This type of XSS vulnerability is also referred to as a '''stored''' or '''persistent''' or '''second-order''' vulnerability, and it allows the most powerful kinds of attacks. A type 2 XSS vulnerability exists when data provided to a web application by a user is first stored persistently on the server (in a database, filesystem, or other location), and later displayed to users in a web page without being HTML |
This type of XSS vulnerability is also referred to as a '''stored''' or '''persistent''' or '''second-order''' vulnerability, and it allows the most powerful kinds of attacks. A type 2 XSS vulnerability exists when data provided to a web application by a user is first stored persistently on the server (in a database, filesystem, or other location), and later displayed to users in a web page without being encoded using HTML entities. A classic example of this is with online message boards, where users are allowed to post HTML formatted messages for other users to read. These vulnerabilities are usually more significant than other types because an attacker can inject the script just once, and could potentially hit a large number of other users with little need for [[social engineering (computer security)|social engineering]]. The methods of injection can vary a great deal, and an attacker may not need to use the web application itself to exploit such a hole. Any data received by the web application (via email, system logs, etc) that can be controlled by an attacker must be encoded prior to re-display in a dynamic page, else a XSS vulnerability of this type could result. |
||
==Exploit scenarios== |
==Exploit scenarios== |
||
Line 61: | Line 61: | ||
There are literally hundreds of examples of cross-site scripting vulnerabilities available publicly. Just a few examples to illustrate the different types of holes will be listed here. |
There are literally hundreds of examples of cross-site scripting vulnerabilities available publicly. Just a few examples to illustrate the different types of holes will be listed here. |
||
An example of a type-0 vulnerability was once found in an error page produced by [[Bugzilla]] where [[JavaScript]] was used to write the current URL, through the document.location variable, to the page without any filtering or |
An example of a type-0 vulnerability was once found in an error page produced by [[Bugzilla]] where [[JavaScript]] was used to write the current URL, through the document.location variable, to the page without any filtering or encoding. In this case, an attacker who controlled the URL might have been able to inject script, depending on the behavior of the browser in use. [https://bugzilla.mozilla.org/show_bug.cgi?id=272620 This vulnerability] was fixed by encoding the special characters in the document.location string prior to writing it to the page. |
||
A recent type-1 vulnerability can be found in older versions of [http://www.atutor.ca/ ATutor], an Open Source Web-based Learning Content Management System (LCMS) written in PHP. [http://www.osvdb.org/17355 This vulnerability] exists in the application's site search page. Script could be injected into nearly every URL request parameter, and the result page would include the malicious script |
A recent type-1 vulnerability can be found in older versions of [http://www.atutor.ca/ ATutor], an Open Source Web-based Learning Content Management System (LCMS) written in PHP. [http://www.osvdb.org/17355 This vulnerability] exists in the application's site search page. Script could be injected into nearly every URL request parameter, and the result page would include the malicious script. |
||
Finally, an example of a type 2 vulnerability was found in [[Hotmail]], in October of 2001 by Marc Slemko, which allowed an attacker to steal a user's [[Microsoft .NET Passport]] session cookies. The exploit for [http://alive.znep.com/~marcs/passport/ this vulnerability] consisted of sending a malicious email to a Hotmail user, which contained malformed HTML. The script filtering code in Hotmail's site failed to remove the broken HTML and [[Internet Explorer]]'s parsing algorithm happily interpreted the malicious code. This problem was quickly fixed, but multiple similar problems were found in Hotmail and other Passport sites later on. |
Finally, an example of a type 2 vulnerability was found in [[Hotmail]], in October of 2001 by Marc Slemko, which allowed an attacker to steal a user's [[Microsoft .NET Passport]] session cookies. The exploit for [http://alive.znep.com/~marcs/passport/ this vulnerability] consisted of sending a malicious email to a Hotmail user, which contained malformed HTML. The script filtering code in Hotmail's site failed to remove the broken HTML and [[Internet Explorer]]'s parsing algorithm happily interpreted the malicious code. This problem was quickly fixed, but multiple similar problems were found in Hotmail and other Passport sites later on. |
Revision as of 22:00, 24 June 2006
Cross-site scripting (XSS) is a type of computer security vulnerability typically found in web applications which can be used by an attacker to compromise the same origin policy of client-side scripting languages.
Terminology
The term cross-site scripting is not a very accurate description of this class of vulnerability. In the words of XSS pioneer Marc Slemko:
This issue isn't just about scripting, and there isn't necessarily anything cross-site about it. So why the name? It was coined earlier on when the problem was less understood, and it stuck. Believe me, we have had more important things to do than think of a better name.
The acronym CSS was often used in the early days to refer to cross-site scripting vulnerabilities, but this quickly became confusing in technical circles because both Cascading Style Sheets and the Content-scrambling system shared the same acronym. Perhaps the first use of the abbreviation XSS was by Steve Champeon in his Webmonkey article XSS, Trust, and Barney. In 2002, Steve also posted the suggestion of using XSS as an alternative abbreviation to the Bugtraq mailing list. In a rare show of unity, the security community quickly adopted the alternative, and CSS is rarely used today to refer to cross-site scripting.
Background
When Netscape first introduced the JavaScript language, they realized the security risks of allowing a webserver to send executable code to a browser (even if only in a browser sandbox). One key issue with this is the case where users have more than one browser window open at once. In some instances, a script from one page should be allowed to access data from another page or object, but in others, this should be strictly forbidden, as a malicious website could attempt to steal sensitive information this way. For this reason, the same-origin policy was introduced. Essentially this policy allows any interaction between objects and pages, so long as these objects come from the same domain and over the same protocol. That way, a malicious website wouldn't be able to access sensitive data in another browser window via JavaScript.
Since then, other similar access control policies have been adopted in other browsers and client-side scripting languages to protect users from malicious websites. In general, cross-site scripting holes can be seen as vulnerabilities which allow attackers to bypass these mechanisms. By finding clever ways of injecting malicious script into pages served by other domains, an attacker can gain elevated privilege to sensitive page content, session cookies, and a variety of other objects.
Types
There are three distinct known types of XSS vulnerability to date. (These will be labeled Type 0, Type 1, and Type 2 for the purposes of this discussion, but these names are by no means industry standard nomenclature. Where possible, other names for these will be provided.)
Type 0
This form of XSS vulnerability has been referred to as DOM-based or Local cross-site scripting, and while it isn't new by any means, a recent paper (DOM-Based cross-site scripting) does a good job of defining its characteristics. With Type 0 cross-site scripting vulnerabilities, the problem exists within a page's client-side script itself. For instance, if a piece of JavaScript accesses a URL request parameter and uses this information to write some HTML to its own page, and this information is not encoded using HTML entities, a XSS hole will likely be present, since this written data will be re-interpreted by browsers as HTML which could include additional client-side script.
In practice, exploiting such a hole would be very similar to the exploit of Type 1 vulnerabilities (see below), except in one very important situation. Because of the way Internet Explorer treats client-side script in objects located in the "local zone" (for instance, on the client's local hard drive), a XSS hole of this kind in a local page can result in remote execution vulnerabilities. For example, if an attacker hosts a malicious website, which contains a link to a vulnerable page on a client's local system, a script could be injected and would run with privileges of that user's browser on their system. This bypasses the entire client-side sandbox, not just the cross-domain restrictions that are normally bypassed with XSS exploits.
Type 1
This kind of cross-site scripting hole is also referred to as a non-persistent or reflected vulnerability, and is by far the most common type. These holes show up when data provided by a web client is used immediately by server-side scripts to generate a page of results for that user. If unvalidated user supplied data is included in the resulting page without HTML encoding, this will allow client-side code to be injected into the dynamic page. A classic example of this is in site search engines: if one searches for a string which includes some HTML special characters, often the search string will be redisplayed on the result page to indicate what was searched for, or will at least include the search terms in the text box for easier editing. If all occurrences of the search terms aren't HTML entity encoded, an XSS hole will result.
At first blush, this doesn't appear to be a serious problem since users can only inject code into their own pages. However, with a small amount of social engineering, an attacker could convince a user to follow a malicious URL which injects code into the results page, giving the attacker full access to that page's content. Due to the general requirement of the use of some social engineering in this case (and normally in Type 0 vulnerabilities as well), many programmers have disregarded these holes as not terribly important. This misconception is sometimes applied to XSS holes in general (even though this is only one type of XSS) and there is often disagreement in the security community as to the importance of cross-site scripting vulnerabilities.
Type 2
This type of XSS vulnerability is also referred to as a stored or persistent or second-order vulnerability, and it allows the most powerful kinds of attacks. A type 2 XSS vulnerability exists when data provided to a web application by a user is first stored persistently on the server (in a database, filesystem, or other location), and later displayed to users in a web page without being encoded using HTML entities. A classic example of this is with online message boards, where users are allowed to post HTML formatted messages for other users to read. These vulnerabilities are usually more significant than other types because an attacker can inject the script just once, and could potentially hit a large number of other users with little need for social engineering. The methods of injection can vary a great deal, and an attacker may not need to use the web application itself to exploit such a hole. Any data received by the web application (via email, system logs, etc) that can be controlled by an attacker must be encoded prior to re-display in a dynamic page, else a XSS vulnerability of this type could result.
Exploit scenarios
Attackers intending to exploit cross-site scripting vulnerabilities must approach each class of vulnerability differently. For each class, a specific attack vector is described here. (The names below come from the cast of characters commonly used in computer security.)
Type-0 attack
- Mallory sends a URL to Alice (via email or another mechanism) of a maliciously constructed web page.
- Alice clicks on the link.
- The malicious web page's JavaScript opens a vulnerable HTML page installed locally on Alice's computer.
- The vulnerable HTML page is tricked into executing JavaScript in the computer's local zone.
- Mallory's malicious script now may run commands with the privileges Alice holds on her own computer.
Type-1 attack
- Alice often visits a particular website, which is hosted by Bob. Bob's website allows Alice to log in with a username/password pair and store sensitive information, such as billing information.
- Mallory observes that Bob's website contains a reflected XSS vulnerability.
- Mallory crafts a URL to exploit the vulnerability, and sends Alice an email, making it look as if it came from Bob.
- Alice visits the URL provided by Mallory while logged into Bob's website.
- The malicious script embedded in the URL executes in Alice's browser, as if it came directly from Bob's server. The script steals sensitive information (authentication credentials, billing info, etc) and sends this to Mallory's web server without Alice's knowledge.
Type-2 attack
- Bob hosts a web site which allows users to post messages and other content to the site for later viewing by other members.
- Mallory notices that Bob's website is vulnerable to a type 2 XSS attack.
- Mallory posts a message, controversial in nature, which may encourage many other users of the site to view it.
- Upon merely viewing the posted message, site users' session cookies or other credentials could be taken and sent to Mallory's webserver without their knowledge.
- Later, Mallory logs in as other site users and posts messages on their behalf....
Please note, the preceding examples are merely a representation of common methods of exploit and are not meant to encompass all vectors of attack.
Real-world examples
There are literally hundreds of examples of cross-site scripting vulnerabilities available publicly. Just a few examples to illustrate the different types of holes will be listed here.
An example of a type-0 vulnerability was once found in an error page produced by Bugzilla where JavaScript was used to write the current URL, through the document.location variable, to the page without any filtering or encoding. In this case, an attacker who controlled the URL might have been able to inject script, depending on the behavior of the browser in use. This vulnerability was fixed by encoding the special characters in the document.location string prior to writing it to the page.
A recent type-1 vulnerability can be found in older versions of ATutor, an Open Source Web-based Learning Content Management System (LCMS) written in PHP. This vulnerability exists in the application's site search page. Script could be injected into nearly every URL request parameter, and the result page would include the malicious script.
Finally, an example of a type 2 vulnerability was found in Hotmail, in October of 2001 by Marc Slemko, which allowed an attacker to steal a user's Microsoft .NET Passport session cookies. The exploit for this vulnerability consisted of sending a malicious email to a Hotmail user, which contained malformed HTML. The script filtering code in Hotmail's site failed to remove the broken HTML and Internet Explorer's parsing algorithm happily interpreted the malicious code. This problem was quickly fixed, but multiple similar problems were found in Hotmail and other Passport sites later on.
A similar example, which was more fatal, was found in Indiatimes Email portal by Sandeep Giri. This example demonstrated that if a mailing service is vulnerable to such kind of attack a victim's inbox can be hijacked even if victim doesn't open the mail sent by malicious user.
Netcraft announced on June 16, 2006. A security flaw in the PayPal web site is being actively exploited by fraudsters to steal credit card numbers and other personal information belonging to PayPal users. The issue was reported to Netcraft via their own anti-phishing toolbar. Soon after, Paypal reported that a "change in some of the code" on the Paypal website had removed the vulnerability.
Avoiding XSS vulnerabilities
Reliable avoidance of cross-site scripting vulnerabilities currently requires the encoding of all HTML special characters in potentially malicious data. This is generally done right before display by web applications (or client-side script), and many programming languages have built-in functions or libraries which provide this encoding (in this context, also called quoting or escaping).
An example of this kind of quoting is shown below, from within the Python interpreter:
~> python Python 2.3.5 (#2, Aug 30 2005, 15:50:26) Type "help", "copyright", "credits" or "license" for more information. >>> import cgi >>> print "<script>alert('xss');</script>" <script>alert('xss');</script> >>> print cgi.escape("<script>alert('xss');</script>"); <script>alert('xss');</script>
Here, the first print statement produces executable client-side script, whereas the second print statement outputs a string which is an HTML-quoted version of the original script. The quoted versions of these characters will appear as literals in a browser, rather than with their special meaning as HTML tags. This prevents any script from being injected into HTML output, but it also prevents any user-supplied input from being formatted with benign HTML.
The ultimate problem with trying to avoid XSS vulnerabilities is that every situation is different. For any given situation, the needs and the issues change. For instance, if user input is going into the src attribute of a hyperlink, cgi.escape() would not be sufficient. Let's say a picture was to be added to a page of pictures, in this fashion:
<img src='$url'>
An attacker could enter "doesntexist.jpg' onerror='alert(document.cookie)" to add an event which triggers when the browser fails to load "doesntexist.jpg", executing the code.
If one were to implement a function like cgi.escape() (which comes with Python), one would be best off converting all but known-safe characters to their equivalent HTML entity. Because browsers implement complex (and often buggy) parsing algorithms for HTML (in all of its flavors), it is difficult to predict what characters could be treated as special. In particular, support for Unicode character sets by browsers could leave an application open to XSS attacks if the HTML quoting algorithms only look for known-bad characters.
As stated above, the unfortunate consequence of this fix is that users are prevented from embedding non-malicious HTML into pages. Because HTML standards do not provide any simple mechanism to disable client-side scripts in specific portions of a web-page, it is difficult to reliably cleanse script from normal HTML. The most reliable method is for web applications to parse the HTML, strip tags and attributes that don't appear in a whitelist, and output valid HTML.
Other forms of mitigation
The easiest way to eliminate XSS vulnerabilities is to encode (HTML quote) all user-supplied HTML special characters, thereby preventing them from being interpreted as HTML. Unfortunately, users of many kinds of web applications (commonly forums and webmail) wish to use some of the features HTML provides. There are some web applications, which attempt to identify all "evil" HTML, and neutralize it, either by removing it or encoding it. These algorithms usually end up being incredibly complex, and for this reason it is almost impossible to know for sure if all possible injections are eliminated. This is because JavaScript has been so tightly integrated into HTML syntax, in addition to the fact that browser and web technologies are still heavily under development. In order to eliminate certain injections, any server-side algorithm must either reject broken HTML, fix the HTML to be well-formed, or understand how every browser will interpret broken HTML.
Besides content filtering, other methods for XSS mitigation are also commonly used. One example is that of cookie security. Many web applications rely on session cookies for authentication between individual HTTP requests, and because client-side scripts generally have access to these cookies, most simple XSS exploits are written to steal these cookies. To mitigate this particular threat (though not the XSS problem in general), many web applications tie session cookies to the IP address of the user who originally logged in, and only permit that IP to use that cookie. This is effective in most situations (if an attacker is only after the cookie), but obviously breaks down in situations where an attacker is behind the same NATed IP address or web proxy. Internet Explorer also has a feature, called the HTTP Only flag, which allows a webserver to set a cookie which is unavailable to client-side scripts. While this seems like a useful feature, it does not prevent using XSS to steal passwords or perform powerful cross-site request forgery attacks.
An additional common mitigation, is to use input validation of all potentially malicious data sources. This is a common theme in application development (even outside of web development) and is generally very useful. For instance, if a form accepts some field, which is supposed to contain a phone number, a server-side routine could validate that the input fit a very specific format (eg "(555) 555-5555"), which eliminates the possibility that it contains any client-side script. (Incidentally, this can also be used to eliminate other attacks, such as SQL injection.) While effective for most types of input, there are times when an application, by design, must be able to accept special HTML characters, such as '<' and '>'. In these situations, HTML quoting is the only option.
Finally, some web applications are written to operate completely without the need for client-side scripts. This allows users, if they choose, to completely disable scripting in their browsers before using the application. In this way, even potentially malicious HTML can be displayed unencoded on a page, and users will not be susceptible to XSS attacks. Many browsers can be configured to disable client-side scripts on a per-domain basis, which greatly enhances the convenience of such a system. The major drawback to this mitigation is that most users are ignorant of such measures, and would not know how to properly secure their browsers for such applications.
Related vulnerabilities
There are several classes of vulnerabilities or attack techniques which are related, and worth mentioning:
- Cross Zone Scripting vulnerabilities, which exploits "zone" concepts in software, usually execute code with a greater privilege.
- HTTP Header Injection vulnerabilities, which can be used to create cross-site scripting conditions in addition to allowing attacks such as HTTP response splitting
- Cross-site tracing attacks, which exploits the HTTP TRACE method to glean more information from a user's browser when a XSS vulnerability is present.
- SQL Injection vulnerabilities, which are much different, but often found in web applications along with XSS holes.
External links
- The Cross-Site Scripting (XSS) FAQ
- XSS Cheat sheet
- CERT® Advisory CA-2000-02 Malicious HTML Tags Embedded in Client Web Requests
- Apache Software Foundation - Cross-Site Scripting Info
- XSS, Trust, and Barney
- The Same Origin Policy
- DOM-Based Cross-Site Scripting
- Second-order Code Injection Attacks
- Post to Pentest list by Tom Gallagher in regard to Type 0 attacks and local zone
- XSS Attacks FAQ - Aelphaeis Mangarae
- Foiling Cross-Site Attacks
- The XSS Blacklist
- Current Blacklist
- Cross-Site Scripting Worm Floods MySpace
- Google XSS Example
- A List Apart - Community Creators, Secure Your Code!
- A List Apart - Community Creators, Secure Your Code! Part II