views:

292

answers:

1

We currently have a group of web-services exposing interfaces to a variety of different client types and roles.

Background:

  • Authentication is handled through SSL Client Certificate Verification. This is currently being done in web-service code (not by the HTTP server). We don't want to use any scheme less secure than this. This post is not talking about Authorisation, only Authentication.
  • The web-services talk both SOAP and REST(JSON) and I'm definitely not interested in starting a discussion about the merits of either approach.
  • All operations exposed via the web-services are stateless.

My problem is that verifying the client certificate on each requests is very heavyweight, and easily dominates CPU time on the application server. I've already tried seperating the Authentication & Application portions onto different physical servers to reduce load, but that doesn't improve dispatch speed overall - the request still takes a constant time to authenticate, no matter where that is done.

I'd like to try limiting the number of authentications by generating an HTTP cookie (with an associated server-side session) after successful client certificate verification, which when supplied by the client will cause client certificate verification to be skipped (though still talking over SSL). I'd also like to time-limit the sessions, and make the processes as transparent as possible from a client perspective.

My questions:

  1. Is this still as secure? (and how can we optimise for security and pragmatism?)
  2. Are there free implementations of this scheme? (I'm aware of the SiteMinder product by CA)
  3. Given the above, should we continue to do Authentication in-application, or move to in-server ?
+3  A: 

generating an HTTP cookie (with an associated server-side session) after successful client certificate verification, which when supplied by the client will cause client certificate verification to be skipped

Is this still as secure? (and how can we optimise for security and pragmatism?)

It's not quite as secure in theory, because the server can no longer prove to himself that there's not a man-in-the-middle.

When the client was presents a client-side certificate, the server can trust it cryptographically. The client and server should be encrypting and data (well, the session key) based on the client's key. Without a client-side cert, the server can only hope that the client has done a good job of validating the server's certificate (as perceived by the client) and by doing so eliminated the possibility of Mr. MitM.

An out-of-the-box Windows client trusts over 200 root CA certificates. In the absence of a client-side cert, the server ends up trusting by extension.

Here's a nice writeup of what to look for in a packet capture to verify that a client cert is providing defense against MitM: http://www.carbonwind.net/ISA/ACaseofMITM/ACaseofMITMpart3.htm

Explanation of this type of MitM. http://www.networkworld.com/community/node/31124

This technique is actually used by some firewall appliances boxes to perform deep inspection into the SSL.

MitM used to seem like a big Mission Impossible-style production that took a lot to pull off. Really though it doesn't take any more than a compromised DNS resolver or router anywhere along the way. There are a lot of little Linksys and Netgear boxes out there in the world and probably two or three of them don't have the latest security updates.

In practice, this seems to be good enough for major financial institutions' sites, although recent evidence suggests that their risk assessment strategies are somewhat less than ideal.

Are there free implementations of this scheme? (I'm aware of the SiteMinder product by CA)

Just a client-side cookie, right? That seems to be a pretty standard part of every web app framework.

Given the above, should we continue to do Authentication in-application, or move to in-server ?

Hardware crypto accelerators (either a SSL proxy front end or an accelerator card) can speed this stuff up dramatically.

Moving the cert validation into the HTTP server might help. You may be doing some duplication in the crypto math anyway.

See if you would benefit from a cheaper algorithm or smaller key size on the client certs.

Once you validate a client cert, you could try caching a hash digest of it (or even the whole thing) for short time. That might save you from having to repeat the signature validations all the way up the chain of trust on every hit.

How often to your clients transact? If the ones making up the bulk of your transactions are hitting you frequently, you may be able to convince them to combine multiple transactions in a single SSL negotiation/authentication. Look into setting the HTTP Keep-Alive header. They may be doing that already to some extent. Perhaps your app is doing client cert validation on every HTTP request/response, or just once at the beginning of each session?

Anyway, those are some ideas, best of luck!

Marsh Ray
Thanks for asking this by the way. After the same question came up three times the same day in slightly different contexts (!) I started digging deeper. Turns out the answer is a little more involved: http://extendedsubset.com/?p=8
Marsh Ray