Hacker News new | past | comments | ask | show | jobs | submit login
Ginzametrics Open Sources Odin, A Cookie-Based Single Sign On for Apache (ginzametrics.com)
41 points by mpasternacki on Aug 14, 2012 | hide | past | favorite | 20 comments

I think this has the HMAC timing flaw. This is a hard flaw to exploit, and a very common one that many people could spot, so:

    die "Invalid signature\n"
        if ( $hmac ne hmac_for($secret, $user, $roles, $ts, $ua) );
The "ne" operator in Perl will terminate at the first non-matching byte. You need an HMAC compare to touch every byte. The idiom is, XOR each successive byte, then reject the hash if the accumulated sums aren't 0.

Also, I'm not wild about a structured cookie with "-" as the separator that contains any user-controlled data. The user-agent is last in the cookie, which is good, but you worry about usernames with the "-" character. "Canonicalization" is the process of ensuring that every piece of data that hits the hash is in a character set that can reliably be extracted from the cookie. For data that is in any way under user control, if you're going to use "-" as a separator, I'd hex-encode the strings.

Thank you for your remarks, this is really helpful.

It doesn't seem to me that timing attack is feasible here: timing of comparison of a relatively short string vs network latency and everything else that happens during Apache's request handling would require a lot of repeated attempts and statistical analysis of very noisy data if it's at all possible to get meaningful results. Still, it's better to be on the safe side and I'm going to close it up.

Sanity check for idea of resolution: adding a random length sleep, 1 to 3 seconds, if HMAC is invalid. This would fuzz the small timing difference in string comparison, and at the same time tarpit any exploit attempts (invalid HMAC is more likely to be sign of manipulation attempt rather than a honest error). Does that make any sense?

Regarding user-controlled data: the context here is that usernames aren't under user's full control (they need to be entered into Google Apps by someone, and also validated). In general case this is a valid issue - a valid login could break the scheme here.

This is in no way an excuse, but rather explanation of my reasoning: the initial idea was to port GodAuth and be at least "kind of compatible", because some people use GodAuth and it might be meaningful for interoperability. Also, as I'm no specialist in crypto (as you can clearly see), I followed the route of not touching crypto-related code that is already written. The issues you've found are strong enough reasons to diverge from GodAuth - especially that GodAuth interoperability is way more theoretical than an actual security issue even if it may not be exploitable. Thank you for reviewing the code and your remarks.

Also, using sha1_hex(secret+...) and calling it HMAC is a slippery slope (see http://netifera.com/research/flickr_api_signature_forgery.pd...). Although it's seemingly not exploitable due to the structure of the data, look into using a proper HMAC (RFC 2104) to prevent length-extension attacks.

Whoah. That is a good catch. I admit, I skimmed this, saw "hmac_for", thought "I'm not a Perl programmer", and assumed it was HMAC.

Guys, fix this ASAP. SHA1(secret || data) (secret-prefix MAC) is totally insecure. (In practice, every valid forgery to this MAC is going to look like x-y-z-useragent-GIBBERISH-evil-content, but you don't want to be relying on that for your security).

Embarrassing (for me).

Thank you! This will be closed up by end of this week. As I wrote in the article and in the presentation, one of main points of open sourcing it is to have people smarter than myself look at the crypto and protocols to find any issues like this. It should be fairly easy to close up.

Glad to have more eyeballs on this. Thanks guys. We're on it.

This is really helpful, thanks.

Seems like exactly what I'd like to eventually use myself - we have a similar backend tooling setup, and I would love to have employees not bother with complicated ACL stuff on our end.

Allowing everyone to just authenticate via Google Apps is a sweet idea. Anyone know of any resources to implement something similar with Nginx? #lazyweb

The Google Apps integration with backend tools makes this a huge time saver for us. Thanks Maciej!

This is really cool. I wanted something like this a while back, and began looking into implementing it for nginx. But one of the services used websockets, so I ended up building a node.js app that combined everyauth (oauth for about 50 different web services) with node-http-proxy. We released it as Doorman:


The one problem that I've had with it is many oauth providers only allow you to specify one allowed redirect URL per app. So it makes it difficult to run a single doorman instance for multiple services.

Could anyone tell me if this would work on Windows? (I typically dev on something like xampp) but I would love to get this working as authing across several apps is very hard problem and creates horrible UX. It would be awesome to see something similar to hybrid auth integrated (http://hybridauth.sourceforge.net/) where we could choose auth providers.

Awesome project looking forward to seeing it progress.


I don't use Windows, so I can't promise anything, but there's nothing there that may prevent it from working on Windows. It's pure Perl, so the code itself is portable. If you have any particular problem, feel free to email me (address should be in the repo); and if you have success running Odin on Windows, I'd be very interested in hearing that too.

Re hybridauth: using different identity providers is somewhere between "it's possible" and "it would be nice to have" priority, unless we actually need it. The idea is to have the SSO for the internal services, and hybridauth seems to be focused on end user and social authentication. Also, Hybridauth itself is PHP; while in principle it should be possible to implement the authorizer app in any language, I'd prefer to keep it in Perl until there's a really, really good reason to switch.

If I work on option on different identity providers, it will still be rather focused on internal services use case than end-user social authentication use case. However, I'd be happy to see and review a pull request implementing social auth if any of Odin's users needs that.

It's kinda like http://www.openfusion.com.au/labs/mod_auth_tkt/ but with more google sauce.

For whatever it's worth, this also uses an unsafe compare (it's also not using HMAC, but it's double-hashing and seems to be more careful about canonicalization).

It's amazing that somebody didn't do this ten years ago.

Did you consider SSL client auth? I'm not sure you will get all the properties you want out of it (ease of logging out, especially); but having used it a bit now, it is a really pretty nice way to do SSO. Plus, it forces you to keep your internal services on HTTPS which is just a good idea anyway (-:

I don't like this idea as a main authentication system for a couple reasons, besides the logout problem. First, it requires team members to register every single browser they'll be using to access the panels – which may also mean being locked out during emergency due to not having a blessed browser nearby.

As I understand the scheme, distributing and deleting/changing clients' public keys to the web servers is basically the same challenge as syncing htpasswd across servers and trying to let users change their passwords. Syncing itself is not an issue, but making it possible (and EASY - any security that gets in the way of getting the job done will be circumvented by users themselves) to add / update / invalidate user's certs by users themselves is not trivial.

It also adds to the proliferation of credentials: Yet Another Key (or even Set of Keys) is just as bad as Yet Another Login And Password.

This is a good idea for a multi-factor authentication, though: require either token / SMS OTP / other out-of-band verification, or a blessed client certificate – basically, pre-authorize certain browsers. This might fly!

You can use SAML for this too, it's a bit more Enterprise-y (read: stupidly complicated) but there are IdPs for php, python and java and SPs for Django and Apache (mod_mellon).

Yup, enterprise-y is what I've been trying to avoid here. A lot of overhead for users that I can count on my fingers without using binary. Also, much of the big SSO systems seem to require the application to be aware of it, which is a showstopper to me: I want to protect with SSO ANY webapp ANYONE has written, even the simplest ones, without having to bother with trying to make it aware of the system. That's the whole point of setting REMOTE_USER: either the app doesn't care about identity (think status panel without any actions), or most likely it is already able to hand off authentication to the frontend http server.

Yeah if you're in the handful of users area it's way overkill. Mod_mellon doesn't quite handle REMOTE_USER but it does set a request variable (MELLON_USER IIRC) so if you have any control over the source at all you can just bodge that in pretty easily (the django bits to grok that are ~4 lines). Also ties you to apache but on the other hand lets you chain authentication to google apps which is gold if you've got a preexisting authentication system.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact