Security/CSP/XSSModule
Overview
This document is a "straw-man" proposal for breaking Content Security Policies into separate modules. In particular, this document defines the XSSModule, which contains the cross-site script (XSS) mitigations. The XSSModule lets web developers mitigate XSS attacks by disabling unneeded functionality used by attackers to mount XSS attacks.
Threat Model
The XSSModule seeks to help web developers reduce the severity of cross-site scripting vulnerabilities in their web sites. In particular, the XSSModule is concerned with defending against an attacker with the following abilities:
- The attacker can inject a sequence of bytes into a target web page.
- The attacker can cause the user to visit the target web page.
- The attacker owns and operates a malicious web site (e.g., attacker.com).
We further assume the web developer wishes to prevent the attacker from achieving the following goals:
- The attacker must not learn the contents of the target web site's cookies.
We assume that the browser properly implements the same-origin policy and does not contain any privilege escalation vulnerabilities.
Syntax
An HTTP server can deliver a policy to the browser by including a header named X-Content-Security-Policy. The general X-Content-Security-Policy header as the following syntax:
content-security-policy = "x-content-security-policy" ":" OWS csp-policy OWS csp-policy = csp-rule ["," csp-policy] csp-rule = future-rule / known-rule future-rule = (anything but ";") known-rule = *SP directive [ 1*SP origin-list ] *SP directive = (see below) origin-list = origin-descriptor [ 1*SP origin-list] origin-descriptor = "none" / "self" / "*" / [scheme "://"] host-descriptor host-descriptor = qualified-host-name / * ["." qualified-host-name ] qualified-host-name = dns-label "." host-name host-name = dns-label ["." host-name]
The XSSModule introduces the following directives:
directive = block-xss / block-eval / script-src
The browser MUST ignore any X-Content-Security-Policy header fields occurring in an HTML meta tag or in the Trailer headers. The semantics of these directives are described in the following section.
Semantics
This section describes the semantics of the directives introduces in the XSSModule. Other modules can re-use the syntax defined in this module provided they do not alter the semantics.
origin-list
The origin-list production defines a set of URLs, which the directive can use for some purpose. The origin-list denotes the union of all URLs denoted by the listed origin-descriptors. The three constant origin-descriptors, self, none, and *, denote the following sets of URLs:
- "self" denotes the set of URLs that share the same scheme and (fully qualified) host name as the current web page.
- "none" denotes the empty set of URLs.
- "*" denotes the set of all URLs.
Instead of a constant, the an origin-descriptor can contain a non-constant origin-descriptor such as the following:
example.com *.example.org https://example.net http://*.foo.example.com
If the descriptor lacks a scheme, then the scheme defaults to the same scheme as the current web page. If the descriptor contains a *, then the star matches zero or more subdomains. For example, *.example.org matches example.org, foo.example.org and bar.foo.example.org. The origin-descriptor, then, denotes the set of all URLs with schemes and (fully qualified) host names that match the descriptor. Notice that in all cases the origin-list ignores port numbers for simplicity.
A resource load is said to respect an origin-list if the initial request, and all subsequent redirects, are for URLs contained in the set of URLs denoted by the origin-list.
block-xss
The block-xss directive is designed to be a first line of defense against XSS attacks. The block-xss directive has two effects:
- The browser MUST NOT execute inline script in the current web page, including inline script elements and inline event handles.
- The browser MUST NOT load external scripts or plug-in objects into the current web page from URLs other than "self", defined above.
- The browser MUST ignore any JavaScript or Data URLs in the current web page.
The block-xss directive blocks inline script because an XSS attacker can run JavaScript by inject script tags or inline event handlers into the target page. The block-xss directive also blocks loading external scripts and plug-ins from other origins to prevent the XSS attacker from injecting a script tag that loads a malicious script from attacker.com.
Notice that multiple block-xss directives are redundant.
block-eval
The block-eval directive is designed to mitigate DOM-based XSS vulnerabilities caused by indiscriminate use of eval and other eval-like features. When present, the block-eval directive has the following effects:
- The eval API MUST ignore its arguments and return undefined.
- The setTimeout and setInterval APIs MUST ignore their argument if the first argument is a string (which would otherwise be evaluated after the given delay).
- The Function constructor MUST ignore its arguments if its first argument is a string (which would otherwise by evaluated when the function is called).
The block-eval directive is not strictly necessary to mitigate reflective or stored XSS vulnerabilities. However, some web developer might find the directive useful as a second line of defense.
script-src
The script-src directive is design give web developers more fine-grained control over from where their web page can load external script. When present the script-src directive has the following effects:
- The browser MUST NOT enforce the restrictions on loading external scripts or plug-in objects given by the block-xss directive because the script-src overrides those restrictions with a finer-grained policy.
- The browser MUST NOT load an external script into the current web page unless loading that script respects the provided origin-list.
- The browser MUST NOT load an plug-in object into the current web page unless loading that script respects the provided origin-list.
In order to mitigate XSS vulnerabilities, the script-src directive SHOULD be used in conjunction with the block-xss directive.
Examples
TODO: Add some examples.
Open Issues
This section contains a list of open issues.
- XBL bindings. We should disable XBL bindings for the block-xss directive, by they are a non-standard feature, so it's unclear how to write normative requirements for them.
- Strict MIME type handling for script-src. I'm inclined to leave that for another directive ("strict-types" or some such). The attack vector is pretty obscure.
- Password theft. The XSSModule doesn't help with password theft because the attacker can make a fake password field. I think we should have a separate module targeted at that issue.