Monday, June 29, 2009

CSP: with or without meta?

We're working up a storm on Content Security Policy (CSP) here at Mozilla, and I've been spending a lot of time hacking out an implementation and talking with people about how CSP works. I keep coming back to sharp edges caused by allowing policies in <meta> tags. Not only does meta-tag support make implementation of CSP more difficult, but it actually also provides an additional attack surface.

What is CSP?
Quick summary of Content Security Policy: CSP lets web site authors specify a policy that locks down where the site may obtain resources as well as what types of resources may be requested. This policy is specified in an HTTP Request header or may also be specified in a meta tag. There's a great blog post by Brandon that talks about this stuff more in depth.

Enter the http-equivalent META tag.
Originally, the point of allowing policy definitions in meta tags was to gain greater flexibility and give an option to folks who can't modify HTTP headers due to web hosting restrictions. Later on, we started thinking that meta-tag-CSP would be a useful way to allow "tightening" or intersection of policies for specific segments of a web site.

The only use case that comes to my mind is a shared web hosting service. Imagine the controllers of a hosting service want to forbid embedding of Flash content from EvilFlashHacker.com; at the same time their customers may want a more restrictive policy, but only one policy can be specified in HTTP. As a result the hosting company has three options:

  1. Let their customers override the policy (possibly removing the no-EvilFlashHacker.com rule)

  2. Disallow the ability for their customers to tighten the CSP

  3. Provide some way to allow policy tightening without the possibility of loosening.

An ability to specify policies in meta tags gives way for situation 3: policy tightening. Unfortunately there are side-effects to allowing policy specification in both HTTP headers and meta tags.

Side Effects.
Implementing CSP becomes quite a bit more complex with meta tags. First, the user agent has to figure out to do when there are two conflicting policies, one in HTTP and one in meta. We solved this with an intersection algorithm that can only tighten an effective policy. Aside from conflicts, there's also the issue of parsing the meta tag out of the document appropriately before any resources subject to CSP are requested.

Allowing policy specification in a meta tag also opens up another use for successful content injection attacks: injection of an unauthorized policy. Additionally, such a policy could be used for a limited CSRF attack on the site itself through a policy-uri or report-uri directive. Of course an unauthorized "allow none" policy can effectively DoS a site, too.

Content Separation.
In the haze of thinking about meta-tag-CSP uses, I lost track of the reason CSP was HTTP header-based in the first place: to separate the content from the transmission channel and underlying policies that controls what it is for and what it can do. There's a clear advantage to this separation: it is harder to attack. Adversaries now must be able to break into the protocol level, not just the application/content. HTTP headers are way more easily hardened on the server-side than an HTML tag.

I want to eradicate meta-tag support for CSP, and all of the thorns that come with it -- policy intersection, document parsing complexity, HTML injection threats, etc -- because I don't think the relatively small gain from implementing it is worth the potential cost and risk. Is there a use (other than the hosting service use case above) that requires a meta tag CSP... and is worth the security risk and code complexity?

Labels: , , , ,

Tuesday, April 21, 2009

roll your own EV

In working on a project recently, I found myself wanting to become an EV-SSL certificate authority (EV means Extended Validation). Lofty goals, yes, but really I just wanted to play with EV certificates and see if a couple of things were feasible. I'll post what happens as I figure it out.

Anyway, I needed to find a way to get a browser to accept a root CA that I created, and then get the browser to trust that root CA to issue EV certificates. This is harder than it sounds; regular SSL root certificates can be added easily to any browser, but the EV root certs can't. This is to protect users from accidental or malicious installation of EV root certs -- but unfortunately also protected me from easily doing it too.

Turns out, Firefox will let you "test" some CA certs as EV authorities, but you have to get your hands on a debugging build. Not only that, but unless you want to maintain a fresh CRL or OCSP server, you'll have to modify the source code. Sounds daunting, but it really isn't too bad. I've documented the whole process here, and I'll summarize in this blog post.

1. Create an EV-SSL Certificate Authority, and make an EV cert. This sounds fancy, but basically means: create a certificate authority, then issue a cert with a specific policy OID. The differences between regular CAs and EV CAs are minimal except in how the browser decides to classify them. In short, this should do the trick:
./CA.pl -newca

openssl req -config ./openssl.cnf -new -keyout newkey.pem \
-out newreq.pem -days 30

openssl ca -config ./openssl.cnf -policy policy_anything \
-out newcert.pem -infiles newreq.pem
Details here.

2. Tame Firefox. This involves patching the Firefox source code to perform lazy freshness checks on certificates (and there's a patch for that here), and set it up to accept externally defined EV root authorities (you will list them in a text file). Then you must compile the source in debug mode to enable it. Details here.

3. Install your CA and go. You have to extract the base-64 encoded subject and serial number out of your CA certificate by installing this patch, compiling the NSS tools, and running the pp tool on your root certificate. Once you've got that data, put it, the EV policy OID of your choice, and the CA cert fingerprint in a file called "test_ev_roots.txt". That text file goes in your Firefox profile directory. Once that's set up, you run Firefox, install the root CA as a regular SSL trusted authority, and you're ready to go. Details here.

Summary. It's not impossible to install a root certificate and get Firefox to consider it an EV root, but it is surely difficult (and this is good). The instructions presented in this post are simply summary, and not indended to be details, which can be found here.

Edit: I guess I should explain that EV means Extended validation; basically a more thorough check is performed by a certificate authority before issuing an EV certificate [EV on wikipedia]

Labels: , , ,

Wednesday, March 25, 2009

ev certs are not so ev

Last week at CanSecWest, Alex Sotirov and Mike Zusman showed how extended validity (EV) certificates don't really provide much additional help to securing a site with SSL. To sum-up a couple of their conclusions:

1. It's not hard to get a regular cert for an interesting domain.
2. An EV-certified site can load data from any other SSL-encrypted locations, regardless of the cert.
3. Rogue cert + MITM + EV-site = arbitrary attack code execution on EV-site.

It seems to me that the problem is rooted in a slight but pervasive misunderstanding of what EV certs do: they provide a more rigorous check to ensure that the entity serving data through the EV certified channel is actually who they claim to be. They don't currently give proof to a site's visitor that the site has not been compromised.

Having said that, if an attacker can prey on the way the site serves content, it doesn't matter whether or not the EV entity is actually who they claim to be; an attacker can just piggyback on their session, serving some cleverly crafted data with a rogue cert. This can be done by playing man in the middle with third-party content embedded on the EV site, or by playing tricks with the browser's cache.

Easy fix: In order to display the green bar (EV badging) require all the stuff on a web page to be served with the same EV cert. This is not attractive for many reasons, including ad syndication and distributed content serving -- both highly desirable uses may cross the fully-qualified domain border and thus require non-EV certs or multiple different EV certs. (EV certs are not allowed to have wildcard domain matching, so any difference in domain name will cause the cert to be invalid).

A more desirable fix, in my opinion, will take a look at the problem from a base level and figure out why EV breaks in these mixed-content or mixed-cert scenarios--then fix EV. The EV cert says "trust my subject at domain.com." What we really need is a way to say "trust this site."

More to come.

Cheers to Sotirov and Zusman for this excellent discovery and PoC man-in-the-middle script.

Labels: , , ,

Tuesday, March 10, 2009

where should web policies be enforced?

I've been spending a lot of time thinking about context-based security decisions lately. These are decisions made on behalf of a website (or its users) in order to maintain data integrity and secrecy. Take for instance the issues of CSRF and Clickjacking; both of these attacks involve some sort of contextual manipulation. CSRF is a HTTP request generated by an untrustworthy source and Clickjacking is data theft by overlaying forms (etc).

There are many approaches to stop these things... but on whose shoulders should the policy enforcement lie? Should a web browser be in charge of making sites safe, or should it just be an enabler that provides enough information to a server so it can make appropriate decisions?

CSRF can be stopped by the browser, but in a fairly convoluted way. It's tough for a web browser to discern which requests will cause a significant transaction on the web server. For example, the simple request

GET /profile/deleteme.do

could be enough to trash someone's account on a server. Even some POST requests don't cause internal state changes (imagine a currency conversion calculator or a POST-based language translator form). It seems a bit easier to stop CSRF on the server where the application itself can decide whether or not to trust each request. This requires the browser, however, to provide some information about the request such as where it came from (but HTTP-Referrer is not reliable) or how it came (such as whether it was from an image tag, etc).

Clickjacking is more easily approached on the client side. One approach is to make an impenetrable fence around certain special frames where any outer/parent frames can't layer stuff on top of their children. This frame-firewall approach is not always attractive, so maybe there should be some mechanism that allows the server to say "hey, this is sensitive, don't overlay this content I'm serving." Then again, maybe it would be ideal to just tell the server a bit about where the content will be rendered, and let the server decide whether or not to serve data.

But what both Clickjacking and CSRF have in common is that they leverage contextual blindness that many web applications have -- they're not aware of where requests come from or where there responses end up.

It seems clear that we can't rely on just a browser-side or server-side fix for these types of things, and instead we need to have some sort of cooperation. The question remains, however, who should do the bulk of the enforcement. I'm currently leaning towards using the browser as a context-revealing tool and leaving enforcement and policy decisions up to the server, but there's many times when that's not enough to stop client-side attacks.

Labels: , , ,

Wednesday, February 25, 2009

career move

I have been trying to keep this blog fairly technical, but since I haven't posted anything in a while and I've more or less changed my main focus, I figure it is relevant to post an update.

Recently I completed my Ph.D. and took a position at Mozilla Corporation. I'm going to be working on the security team there to protect the internets. Eventually I'll get back into the groove of posting relevant information to this blog (since I'll keep my focus in the security/computing realm) but it might take me a while to ramp up. In the meantime, thanks to all those nice folks at Mozilla who have been helpful with my move.

Labels: , ,

Thursday, October 02, 2008

lappy goes down

Yesterday my laptop's hard drive made some funny noises, so I shut the sucker down, and guess what? It wouldn't come back up.

I replaced the drive with a 250GB one (bigger and cheaper than an exact "Death Star" replacement from an Apple dealer), then restored from TimeMachine backup (pretty slick, actually), and am now trying to figure out what is broken.

  1. Fink stopped working, but probably due to me being stupid (found an error in a config file, and easily fixed Fink)

  2. Had to reinstall developer tools.

  3. Needed to perform software update twice before mail worked


Other than that, time machine saved my butt. Now to recreate the last week's worth of work, and to convince myself to do daily backups instead of weekly ones.

Saturday, March 22, 2008

tax phish

Tax Phishing season is open. Go catch yourself a good one!

Labels: , ,

Monday, March 10, 2008

iphone's ambiguous http-auth


I'm a little disappointed at Apple. While I think the iPhone is a pretty nice piece of work and their browser is pretty nice too, I don't like the way it handles HTTP-AUTH. (There are other gripes I have, like no "find" feature in safari or the mail app, but we'll stick with a security problem for now). Most browsers are kind enough to display on the "safe" pop-up login box which which website requested the authentication. This is not so with iPhone Safari.

Not only does the pop-up "enter your password" box fill the whole screen (a rather necessary evil), but it doesn't display the domain, URL or any information about the website where you're sending your credentials. If I had some free time, I would hack together a quick demo to show how, using iframes (suitably) or images, I can make you think you're logging into one site but you are actually sending your password to another one entirely. It does indicate whether you are sending your password in the clear or if the connection is secured with TLS/SSL, but in a subtle gray font under the login boxes.

I want to know where my password goes!

Labels: , ,