KENNETH LEE: Yeah, so just letting you
all know I posted a copy of the slides on my Twitter,
which is @Kennysan.
So if you want to follow along, you can just download a copy
the speaker deck from there.
Let's begin.
Hi, DEF CON.
(Applause.) KENNETH LEE: So this is my talk, How
to Use Content Security Policy to Stop Crosssite Scripting.
First a little bit of detail about myself.
My name is Ken Lee.
I'm a product security engineer at Etsy.com.
In a previous life, I worked at a financial software company.
As I just told you literally 30 seconds ago, my Twitter handle is @Kennysan.
If you have any questions, you can feel free to e mail me
or send me a Tweet.
So let's talk about content security policy
because I assume that's the reason you're all sitting here today.
The best way I've heard content security described,
it's essentially depth for the web.
By that I mean, it is a way to tell for a server to tell your browser,
you're allowed to execute certain things,
and only these things that I tell you to execute.
By doing that, it provides for a mechanism
to stop crosssite scripting from happening.
Just by a show of hands, how many people
in this room know what crosssite scripting is?
Okay.
All right.
Then this slide is going to go extremely quickly.
So, for example, I take a page to HTML and I throw
a simple crosssite scripting inside of it.
This page has content security policy on it.
If you look at the bottom of the page, the actual execution of the script
is blocked by the presence of a content security policy.
That's sort of basically how it works.
Now, for more detail, the way that it works is that
a browser that is following a content security policy only follows
specific directives specified by the content security policy
as elements that it's allowed to render or execute on the page.
In particular, the two important things to note
about this is that content security policy
by default disallows the use of inline JavaScript on a page, which
is a big thing that I'll get to later.
And in addition, it prevents the use of the eval style family
of functions in JavaScript.
So I'm just kind of throwing this up there.
This is an example content security policy header.
You know, you're not expected to understand this.
There will be no quiz later on this.
This is to demonstrate what a content security policy looks like.
It's basically specified as a set of directives with a set of URIs
and keywords that tells the browser what you are allowed
to execute JavaScript and other elements from.
So content security policy, as I've said before, is broken
up into a series of directives.
The most common ones that you will probably end
up using are directives such as script source, which controls
the use of JavaScript on a page; style source, which controls use
of CSS and other styling on a page.
And as you can see here, there's a directive
for pretty much most types of things that you can embed
on a web page.
In addition to that, there are also special keywords that
you can use in combination with the directives
to modify your content security policy.
So, for example, specifying a keyword of "none"
for script source directive tells the browser don't accept any sources,
don't allow any JavaScript from any source.
The self directive is pretty self explanatory.
It basically says for only allow content
from the same subdomain and scheme.
And the "unsafe inline" and "unsafe eval" are special keywords
that actually override the default functionality that
I mentioned before with regards to content security policy blocking
inline JavaScript and eval.
So, an important aspect of content security policy that I'm going
to go into is the use of "Report Only Mode" .
Report Only Mode, basically it's appended to the end
of your content security policy header or content security policy meta tag.
What this allows you to do is it tells the browser, I want you
to not actually block elements that are disallowed
by the content security policy.
So it's essentially a dry run.
And what makes this functionality even more powerful is the use
of a report URI.
So at the end of your content security policy you can
actually specify a reporting end point which tells
the browser, hey, you've seen some bad shit
with content security policy violations, send those violations my way.
And this basically provides a mechanism for the server
to learn what kind of content security policy violations
the server is seeing.
And again, to emphasize, what's important
about report only mode is that it doesn't actually block.
So you can deploy this without actually affecting content that
the client is seeing.
So an important aspect to note is that content security policy
as a standard is still evolving.
This little snippet of a screenshot was taken
from a version of Firefox not too long ago.
It's hard to read the text.
What it basically says is, CSP 1 failed to parse, unrecognized,
directive unsafe inline.
Firefox at the time that the screenshot was taken had
a bug where it didn't recognize the unsafe inline
or unsafe eval directive.
And I think the latest version of Firefox, Firefox 23, actually still has
a bug where it doesn't allow you to white list unsafe style
source elements.
So like I said, browsers these days are mostly
up to spec with regards to CSP 1.0 compliance,
but if you happen to notice in the process of your testing
for content security policy that you're seeing unexpected behavior, there
is a strong possibility it may not necessarily be your content security
policy, it could be the client's browser acting
like a smelly lobster.
So let's talk a little bit more in detail about the inline JavaScript bit
that I alluded to earlier.
So as I mentioned, content security policy 1.0 disallows
by default the use of inline JavaScript on a page.
This is kind of a big deal.
The way that is recommended to sort of deal with inline JavaScript
is to create external scripts out of all your inline JavaScript.
This has kind of a number of implications,
the biggest one being that you're essentially turning
all these inline bits of JavaScript into synchronous calls that
the browser has to retrieve the JavaScript from.
Alternatively, if you want to get around this,
you can always specify the, as I mentioned before,
the unsafe inline directive.
But this has implications for defeating, basically weakening the strength
of you content security policy.
And in addition, if you use any kind of asynchronous job script loading
library, such as RequireJS, this also has implications as well.
Because RequireJS and other asynchronous job script
loading libraries, what they like to do is they essentially like to say, hey,
I want to load this bit of JavaScript, so at some point
during the rendering of the page I'm going
to basically call appendChild to the head of the document
with the contents of the JavaScript.
And because this is all done asynchronously,
it's very fast.
There's no additional HTTP call, but the problem is that's going
to cause issues with content security policy 1.0.
So as a result, there are potential performance
implications to deploying CSP 1.0 by turning all of your scripts
into externalized bits of JavaScript.
Hopefully, content security policy 1.1 will fix that.
As of right now they're sort of working out the final bits of the spec,
but there will essentially be a way to safely white list inline JavaScript
on the page.
So, let me talk about some real world implications
about deploying a content security policy
to your production website.
So oh my God, this is terrible.
So, there's a couple questions that a lot of you probably have
if you want to if you're thinking about rolling
out a content security policy to your website.
For example, how should you go about it?
How should you test the validity of your content security policy?
And what bits should you throw the content security policy onto?
A number of websites; Twitter, for example, have chosen to focus
the content security policy on specific segments of their website.
And this actually makes a lot of sense
from a metric standpoint because it gives you
a very focused approach to applying and fixing
the issues that your content security policy detects.
So these are two just graphs of Splunk, showing a hit count
of content security policy violations that have been sent
from client browsers using the report only directive
to an end point that I've specified.
And in addition, this the bottom graph shows a list
of top blocked URIs.
So what's really powerful about content security policy
is if you specify a report only end point, you can use this to essentially learn
all the things about about content security policy
violations that clients are seeing.
And this potentially has some really interesting implications.
In the process of looking into content security policy
during the evolution of the spec, one of the things I noticed was
the fact that you end up seeing a lot of mixed content on your website.
And the nice thing about content security policy
is that it's actually really effective at helping you root out and stamp
out all those instances of mixed content on your website.
So essentially the technique that one can use
for detecting this mixed content on your website
is if you specify content security policy and you have a reporting end point,
if you see the reporting end point, the browser essentially sends
a JSON blog to the reporting end point containing
information such as document URI, the URI of the blocked element,
what have you, and so basically if you just parse this blog and detect
if the scheme of the document scheme that was
retrieved was HTTPS, and the blocked URI was HTTP,
then you have an instance of mixed content on your website.
Certain headers such as the HTTP strict transport security
can actually be an effective approach in essentially removing mixed content
from your website because this will force
all your subdomains to HTTPS.
But from an implementation standpoint, from experience,
I've discovered that most of the issues you'll run
into with mixed content on your website when rolling
out a content security policy won't be from your own subdomain, surprise,
surprise, it will actually be coming from, in most instances,
third party vendors who simply don't have HTTPS end point for their website.
So a couple thoughts, additional thoughts
about content security policy.
As I mentioned before, unsafe inline and unsafe eval
essentially severely nerf their protective abilities that content security policy
gives to you.
So it's important when deploying a content security policy
to consider whether or not you should include
these directives in your policy.
In addition, content security policy can, if you choose to implement it
as a header, you can potentially be including a very,
very large number of sources in your policy,
and that can cause your header sizes to grow, which can potentially have
an impact on performance.
And the final last point, you should always make an effort
to test your content security policy before you roll out to production.
So let me get to the final, the good bits, before talking about the tool I created.
So if you want to test content security policy right
now, live, it's a thing that exists in Firefox 23 and Chrome 25.
Previous versions of this browser used, I believe, the X content security policy
header for older versions of Firefox and
the X WebKit CSP Header for Chrome.
And if you want, you can test this out, you can apply
the "report only" header or as a meta tag to simply have
the browser attempt to attempt to basically not block instances
of bad JavaScript or style elements that it sees.
In addition, the report URI is tremendously powerful
from a metrics perspective just because of the fact that it can give you
so much information on what clients are actually potentially
seeing in terms of blocked content.
And with the ability to monitor all of this blocked content via either
Splunk, or Status V, or Graphite, or some other logging metrics tool you
use, it gives you the ability to look into and fix all of your inline JavaScript
issues that are caused by deploying a content security policy.
All right.
So let me talk a little bit more indepth
about the tool I'm releasing.
So one problem that I initially ran into when deploying
a content security policy was that it was actually really annoying
to test my content security policy in a development environment
and then push it to production because of the very nature
of the fact that in production, I would have to specify prod hosts,
and in dev I would have to use dev hosts.
It was annoying to the point I didn't want to have
to constantly poison my host file to have to handle this.
So I decided, F it, I'm going to make some tools
to help me fix this problem.
So CSP Tools is essentially a set of three python based tools that do
the following: The proxy tool is essentially
a python proxy written using live in proxy that intercepts all HTTP
and HTTPS traffic.
What you will do if you connect to this proxy, it will insert,
dynamically insert a content security policy report only
header with the policy you specified.
In addition, the proxy will capture any content security policy
violations the browser sends back to the proxy end point.
The browser tool is basically
a selenium powered instance of FireFox, what that does
is allows you to create uni tests for content security policies that you've
deployed to specific pages on your website.
And finally, the parsement tool, which is fairly self explanatory,
what that does AUDIENCE: Excuse me, hi.
So have you attended any Cons?
KENNETH LEE: In past DEF CONS, yes.
AUDIENCE: Okay.
So we're here to actually help you out.
This is your first time speaking; right?
KENNETH LEE: Yeah.
AUDIENCE: How's he doing?
(Applause.) THE AUDIENCE: As many of you know, we have a little tradition,
as our speaker does not seem to know, where all the first time speakers must
do shots.
We also have some other first time attendees to DEF CON.
(Applause.) AUDIENCE: There you are.
KENNETH LEE: Thank you, sir.
AUDIENCE: Congratulations.
Cheers.
KENNETH LEE: Oh, my God.
AUDIENCE: Now, where's Heather?
Heather, raise your hand.
Yep, it's Heather's first time at DEF CON, too.
Give it up for Heather.
(Applause.) KENNETH LEE: All good.
AUDIENCE: And now back to our regularly scheduled oh, shit,
your time's up.
KENNETH LEE: Sorry folks, no demo.
Just kidding.
So here's a little demo of the CSP proxy at work.
I'm browsing through this site, www.etsy.com, you may have heard
of it before.
Wow, that really hit me hard.
So I'm going to the console to demonstrate.
There's no tricks up my sleeve.
No content security policy here.
Going to the network tab to showing you
the Get request does not have content security policy specified
in the response.
So scrolling back down, you can see, no tricks here.
So I'm going in a second, when this really slow video demo
finishes, I'm going to change my proxy settings
for Chrome to specify using a proxy 8080.
If I'm talking a little slower, it's because I just had a lot of alcohol.
And now more alcohol.
(Applause.) KENNETH LEE: Yeah.
So I'm starting up a proxy on and I'm specifying a host
of www.etsy.com, and then I'm going to reload the page now that
the browser is using this proxy.
And you can see here from loading the page,
it's seeing some content security policy violations.
If you look at the initial "Get" request we can see that
a content security policy report only header is in the first response
from the server.
And if we and we can see here
a content security policy violation being sent back to the proxy.
And in addition, we have a number of content security violations being
logged on the console.
So that's essentially how the proxy tool works.
If you actually look into the log file that's generated
by the proxy, all it is, like I said before, no lies, I wouldn't do that to you guys,
it's just simply JSON logs of the content security policy violations
that the proxy has logged to disk.
All right.
So now this next video is demoing the parser and browser tool.
I'm going to load up the proxy again, this time on port 8090, and I'm going
to fire off the selenium powered browser tool.
And I've specified a number of URIs, specifically five, and a number
of HTTP and HTTPS links for the browser to log to.
And since I've specified my proxy on port 8090 for the browser to use,
it's going to connect directly to the proxy and send,
as you can see in the background, send content security policy violations
directly to the proxy.
So you can see here, I'm browsing a couple of URIs, first
the front page of Etsy, now some HTTPS links,
which it loads just fine, and you can tell the proxy
is chugging away happily because it basically just logs
all content security policy violations right off the bat.
And I'm going to jump ahead.
So I implemented this using basically selenium.
If you really wanted to, you could modify this to make
the whole thing run headless so you don't have to see the browser running.
So now we close down the proxy after the browser is done running.
We're going to look at our CSP violations.
You can see we have a ton of them and they've hit
the URIs that we specified, which is excellent.
So now we can go about the process of making
a content security policy using the parsing tool and, damn,
we just created a content security policy
for our website.
(Applause.) KENNETH LEE: So, yeah, if you want to get CSP Tools,
it's available on GitHub at the following URL.
Feel free to issue pool requests if you find bugs
with my implementation.
If you have questions, hit me up afterwards in the QA lounge or
on Twitter, which is, again, Kennysan if you would like to view a copy
of these slides.
I'd also like to give a huge shout out to Kai San
for helping me tremendously with the initial implementation of CSP,
and also just a general shout out to the Etsy security team
of being tremendously supportive of my efforts
in implementing content security policy.
(Applause.) AUDIENCE: Drink.
KENNETH LEE: Oh, my God.
Okay.
Oh, my God.
You guys are the worst I mean the best.
So again, if you want to ask questions, the QA lounge
outside is the appropriate place to be asking them, at least
from what I've been told.
So thank you.