
Ginzametrics Open Sources Odin, A Cookie-Based Single Sign On for Apache - mpasternacki
http://www.ginzametrics.com/blog/announcing-odin-authenticator
======
tptacek
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.

~~~
gose1
Also, using sha1_hex(secret+...) and calling it HMAC is a slippery slope (see
[http://netifera.com/research/flickr_api_signature_forgery.pd...](http://netifera.com/research/flickr_api_signature_forgery.pdf)).
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.

~~~
tptacek
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).

~~~
mpasternacki
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.

------
josegonzalez
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

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

------
mnutt
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:

<https://github.com/movableink/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.

------
xorman
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.

~~~
mpasternacki
Thanks!

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.

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

~~~
tptacek
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).

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

------
antifuchs
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 (-:

~~~
mpasternacki
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!

------
skorgu
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).

~~~
mpasternacki
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.

~~~
skorgu
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.

