On Wed, Mar 02, 2005 at 09:25:09AM +0100, Branko ??ibej wrote:
> Ben Reser wrote:
> >However, the client side problem is much trickier. In order for caching
> >to work with all authentication protocols we must cache the plaintext
> You don't actually have to store the plaintext on either the client or
> the server if you're doing CRAM-MD5, which svnserve does; you can store
> an intermediate result instead. That keeps the passwords secure on the
> server side (but not, of course, on the client side, where the
> intermediate result is just another way to say "plain text password").
First to respond to Branko specifically, note that I said all
authenticatin protocols. Yes there are ways with specific protocols
e.g. CRAM-MD5 that lets us avoid writing the actual plaintext. But as
you point out it's really just as good as the password anyway.
Here's my thoughts on what I'm planning to do:
Ultimately, there aren't really very many solutions to the client side
caching problem. But I also don't think what we're currently providing
is what users really want.
I don't believe that most users want to enter a password once and then
never have to enter it again for that repository. I think most
users simply want to avoid typing the same password in many times in the
same session. This is especially problematic considering that our
client only stays running for brief periods of time to carry out a
specific task in most cases (though there are exceptions like TSVN and
Solutions for the client side I think are as follows.
Implement a svn-pwagent program that will handle password caching for
authentication protocols that transmit hashed information across the
network and for certificates. The agent would not actually reveal the
password the any client using it but would perform the calculations
needing the password for the client. i.e. calculating the hash or
retrieving the session key for things like SSL.
Anyone with access to the svn-pwagent would of course be able to request
that we do calculations for them for other protocols that happened to
use the same authentication protocols that we used. But only for as
long as the program was running. The password would not be forever
revealed to them.
This of course would not help anyone using plain text authentication
methods. However, there is no safe way of caching this information.
Incidentally, I'm not sure how well this can be implmented before 2.0.
Currently our authentication provider architecture doesn't know anything
about the specific authentication method being requested. I believe
we'll need to redesign the authentication provider system to support
this in a clean way. However, we might be able to write a separate
provider that handles "simple" authentication. Frankly, I just haven't
investigated how well the RA layers can be adapted to handle this. I'm
suspecting that it's undesireably ugly to do this without new APIs.
Storing the MD5 contexts (the term used by md5) would indeed alleviate
the majority of the server side concerns, but I don't think it resolves
the real issue. The concern most server admins make is that they're
concerned with people glancing at the passwords while they're working on
the file or with themselves actually seeing the passwords. The concern
with other people seeing is obvious. But seeing other users passwords
isn't a problem for the admin because he already has full access right?
This is true, but the retort always is that users recycle passwords and
that this recycling of passwords gives them access to something they
Storing the contexts stops the admin from directly reentering a password
that they happened to see into any random protocol. However, if you
store the contexts and the other service that this password was recycled
on happens to also use CRAM-MD5 to protect its wire communcations, they
now can generate the final response to authenticate for that service.
The ultimate, gotcha on this issue is that the more services that use
CRAM-MD5 to secure passwords, the less valueable storing the contexts as
a method of protecting from such attacks really is.
Ultimately, you have a choice, you can do authentication in one of two
a) Server stores a one way hashed copy of the password. Client sends
the plaintext password. Server recalculates the password into a hash
and compares it to the hash it has stored. This protects against admins
using the password database to gain access to other services which use
the same password but may or may not protect the password while crossing
the network (see later). However, it still leaves the plaintext
password vulnerable to being in the servers memory. Though well coded
apps will place the password in non-pageable memory and clear and free
that memory as soon as they are done calculating the hash.
b) Server stores a shared secret, this might be the actual password or
some intermediate result of the password. Server sends a challenge that
includes a random component. Client responds with the result of a keyed
one way hash using the shared secret as the key and the challenge as the
text. Server calculates the hash with its own copy of the shared secret
and compares what the client sent to what it calculated.
In the case of an open source app (though being closed source doesn't
necessarily ensure more security here) it would be trivial to make it
accept the intermediares as the password. In fact that's what Branko's
point is about the intermediares being as good as passwords on the
client is about. Since if we store intermediares as the cache for the
client then you can just manually generate a cache if you know the
intermediaries. But even if we don't use this to cache the passwords,
then our client could be trivially modified to accept the
intermediaries. In fact you could probably just write an authentication
provider for it and add it to the list.
Would we be making people feel better if we did this? Probably. Would
we be buying any security? Some, but only for services that don't use
CRAM-MD5. IMHO this is a bad solution as it is realistically impossible
to evaluate this for the problem people are complaining about. You
can't possibly know ever service the user has recycled their password
on. And the evaluation would change over time. Maybe right now you're
using POP3 with plaintext passwords. But what if you switch to IMAP
using CRAM-MD5. Suddenly a hole is opened that wasn't there before.
What's the better solution?
The ideal solution is to ues publice key cryptography. Server and
client has a public/private keypair. Each only knows the others public
key and their own public and private key. In this way they know that
they are communicating only with each other. However, many people are
not willing to use certificates becuase they find them inconvient to
generate and use.
So the stop gap measure is to use server side certificates, to verify to
the client that it is talking to the right server. And then to send the
password in plaintext over the encrypted session based upon a key
exchange via this server public/private keypair.
So my solution for svnserve is as follows:
Implement a PLAIN authentication method. The PLAIN authentication
method will be configurable to be used only when the session is
encrypted (defaults to this configuration). It will work with hashed or
unhashed password files (for backwards compatability) again defaulting
to the more secure position of only using hashed password files.
Now of course this exposes users to the possiblity of revealing their
plaintext password to some bad server if the real servers certificate is
revelead to some unsavory character or the user simply ignores warnings
about the certificate changing. But it solves the problem that we're
trying to deal with here.
So let's consider the end result. Server admins can have password
databases that do not allow them to use the users authentication
information. Clients can have the ease of only having to type their
password ocassionally, without having to worry about someone stealing
their authentication information from on disk caches.
But what about when you want both of these things? There are only 2
a) svn+ssh using client keys and ssh-agent. We already fully support
this. It just works. However, some people are uncomfortable with the
shell access. It's not as easy to setup as some might like, especially
in light of file system permission issues with the repository.
b) http or svnserve with ssl using client certificates for
authentication. We also already support this for http and work is
currently going on to add ssl to svnserve. However, we currently don't
support a reasonably safe way of caching the certificate password at
People with these concerns can be pointed towards these solutions. This
is exactly the course that ssh took. It makes a lot of sense and I
think the vast majority of security concious installations are using
client keys as opposed to passwords for ssh.
Ultimately, not everyone can have their cake and eat it too. But we can
provide some limited but reasonably secure solutions for people with
these concerns. We will have to educate users about the various trade
offs of these solutions and let them choose for themselves which one is
best. Switching to storing something that is just as good as a password
removes our ability to educate these users and let them have a more
secure system and ultimately compromises our abilitiy to claim that this
project claims about security.
Implementing obfuscation routines that makes users feel safer but
doesn't stop the attacker will only earn us a bad reputation when
someone takes advantage of that. We need to remember that users trust
us to be looking out for their security here. If they open up a
password file or cache and see "garbage" they're going to feel safe.
They won't evaluate the full security implications of what we're
actually doing. But if they see a plaintext password they know the
security implications without a doubt.
In summary, I think the project policy should be:
"Secure after a thorough review or obviously insecure."
Ben Reser <email@example.com>
"Conscience is the inner voice which warns us somebody may be looking."
- H.L. Mencken
To unsubscribe, e-mail: firstname.lastname@example.org
For additional commands, e-mail: email@example.com
Received on Thu Mar 3 04:49:31 2005