2013 in Canberra, Mozilla's François Marier presented a
talk on the Content
Security Policy (CSP), the browser-maker's proposed approach to
thwarting cross-site scripting attacks with a framework of
granular restrictions on what types of content a page can load.
We covered CSP in July 2009, just a
few months after development started. Since then, the idea has been
expanded, and, in November 2012, version 1.0 was declared a Candidate Recommendation by the
World Wide Web Consortium (W3C).
Cross-site scripting attacks, Marier explained, usually occur when
input and variables in a page are not properly escaped. An
unsanitized variable such as a user input field allows an attacker to
visitor's browser. Even the templating systems used by modern content
management systems (CMS)—many of which auto-escape content—are
not foolproof. CSP offers an additional layer of protection, argued
Marier, because it is implemented as an HTTP header to be delivered
by the web server and not by the CMS. Thus, for an attacker to defeat
a CSP-equipped site, he or she would have to compromise the web
server, which is arguably more robust than the CMS.
A CSP policy is declarative, in which a site or web application
specifies the locations from which it wishes to allow scripts and
other page content to load. The header declares one or more
src directives, each of which specifies a list of acceptable
URIs for a specific content type. For example, the most basic policy
permits only loading content from the same site—in this case
meaning matching the protocol scheme, host, and port number. The
specification includes nine src
, and connect-src
directive can be set to none
, or to a set of space-separated
expressions, optionally featuring the *
wildcard. URI values are
matched according to a standard algorithm that looks for
scheme:host:port syntax. For example, the directive
img-src 'self' data ;
from a site at www.foo.org would match both www.foo.org
. A site that uses external hosts for content
delivery or to serve ads would need to specify more complicated rules.
There is also a special reserved expression for allowing inline
content (such as inline scripts or CSS), which is somewhat editorially
named unsafe-inline as a reminder that permitting such inline
content is a risky prospect. The reason this warrants the
unsafe moniker being written
into the specification itself, said Marier, is that a browser has
no way to distinguish inline scripts that are written into the page at
the original server from any scripts which are injected into the page
content by an attacker.
The default-src directive allows
site owners to set a restrictive generic policy, which is then
overwritten only by whitelisting
specific additional content types, he said. At his personal site,
fmarier.org, he has the default-src directive set to
none and only turns on additional directives for "minor
At the moment, CSP is available and "works really
well" in Firefox and Chromium/Chrome, and is somewhat
functional in Safari 6 or greater. Nevertheless, he continued, one
does not need to jump directly into converting one's sites over to
full CSP, which can be tricky to get right on the first try. He
instead suggested a few steps to implement CSP progressively.
The first step is removing all inline scripts and styles from the
site's pages. Simply moving them to external files should not affect
page functionality at all, and it removes the need to worry about
unsafe-inline (although, it should be noted, external scripts
and stylesheets do mean longer load times). The next step is to remove all
rewriting. Then one can proceed to implementing a CSP policy. Marier
recommended starting with a "relaxed" and permissive policy, then
working one's way progressively toward a stricter policy.
For this, CSP provides a helpful report-uri directive.
Unlike the other directives, report-uri does not set policy;
it tells the browser to report a policy violation to the URI provided
as the value. The example Marier provided is:
which, he said, would allow one to log false-positive matches. It is
important to note, however, that when report-uri
is in place,
CSP does not
block the rule violations it catches, so it is
vital to remove it once testing is complete.
Marier also recommended that interested site administrators add
their CSP rules in the web server, not through their CMS or
application framework, specifically to provide the extra layer of
protection described above. It is also useful as a reminder that CSP
is a complement to standard cross-site scripting hygiene, and not a
replacement for input escaping. There are some resources out there
for site maintainers to get started with policy writing, he said, such
as CSPisAwesome.com, a tool for
generating valid policies.
For users who are keen to get the benefits of CSP but cannot wait
for their sites to get it rolling, he recommended installing a browser
extension that implements CSP on the client-side. There appears to be
just one at the moment: UserCSP
for Firefox. This extension allows users to write policies for the
various sites they visit, which Firefox then applies just as it would
a CSP header originating from the server. Obviously, the user needs
to be aware of the risks of "injecting" (so to speak) CSP into their
browser, since applying a user-crafted policy could break the
site's functionality. On the other hand, by putting the policy
decision in the user's hands, the user can find his or her own balance
between what breaks and what risks are left open—as is the case
with other client-side security extensions like NoScript.
HTTPS, almost everywhere
As a "bonus header," Marier also discussed the HTTP Strict
Transport Security (HSTS) policy framework with the time remaining in
his session. HSTS, like CSP, is an HTTP header mechanism. It is
designed to protect again SSL downgrade attacks, in which an HTTPS
connection is stripped down to HTTP, presumably without attracting the
user's attention. HSTS allows the server to declare that it will
only allow browsers to connect over HTTPS. The header does not fix a
permanent condition; it includes a max-age directive giving a
time in seconds for which the browser should cache the HSTS setting.
Firefox has supported HSTS since
Firefox 4, but as a question from the audience revealed, it comes with
one hangup: the browser must successfully connect to the server over
HTTPS the first time in order to get the HSTS header.
Mozilla sought to alleviate the risk of attacks that exploit this by
shipping Firefox 17 pre-loaded with a list of verified banking web
sites that the browser should access over HTTPS the first time.
HSTS is supported in Chromium/Chrome in addition to Firefox, as
well as in Opera. Mozilla cannot do much to implement security policy for other
browsers—particularly the proprietary ones—so when asked
what to tell users of other browsers, Marier's response was "It works
in these browsers. If it doesn't work in your favorite browser
... switch browsers."
That is probably sound advice, which a lot of free software
security mavens would echo. But it is interesting to see that,
with both CSP and HSTS, Mozilla is pushing forward on web security from
the server side as well as within the browser itself.
to post comments)