Re: MD5 authentication needs help

From: Stephen Frost <sfrost(at)snowman(dot)net>
To: Bruce Momjian <bruce(at)momjian(dot)us>
Cc: PostgreSQL-development <pgsql-hackers(at)postgreSQL(dot)org>
Subject: Re: MD5 authentication needs help
Date: 2015-03-04 18:27:32
Message-ID: 20150304182731.GG29780@tamriel.snowman.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

* Bruce Momjian (bruce(at)momjian(dot)us) wrote:
> On Wed, Mar 4, 2015 at 12:43:54PM -0500, Stephen Frost wrote:
> > > What does storing multiple hash(password || stoarage_salt) values do for
> > > us that session_salt doesn't already do?
> >
> > By storing a hash of the result of the challenge/response, we wouldn't
> > be susceptible to attacks where the user has gained access to the
> > contents of pg_authid because the values there would not be (directly)
> > useful for authentication. Today, an attacker can take what's in
> > pg_authid and directly use it to authenticate (which is what the
> > interwebs are complaining about).
> >
> > We wouldn't want to do that for just a single value though because then
> > there wouldn't be any value to the challenge/response system (which is
> > intended to prevent replay attacks where the attacker has sniffed a
> > value from the network and then uses that value to authenticate
> > themselves).
>
> So you are storing the password + storage-salt + session-saltX, where X
> is greater than the maximum number of login attempts? How do you know
> the attacker will not be given a salt that was already seen before?

The password isn't stored and I don't know what you're talking about
regarding the number of login attempts. Further, we don't know today if
an attacker has seen a particular challege/response sequence or not (nor
can we...) and we can certainly repeat it.

> > The only way we can keep the session salt random without breaking the
> > wireline protocol is to keep the raw data necessary for authentication
> > in pg_authid (as we do now) since we'd need that information to recreate
> > the results of the random session salt+user-hash for comparison.
> >
> > This is essentially a middle ground which maintains the existing
> > wireline protocol while changing what is in pg_authid to be something
> > that an attacker can't trivially use to authenticate. It is not a
>
> I don't understand how this works.

Ok, let me try to explain it another way.

The current system looks like this:

client has username and password
server has hash(username + password)

client:

send auth request w/ username and database

server:

send random salt to client

client:

send hash(hash(username + password) + salt) to server

server:

calculate hash(hash(username + password) + salt)
compare to what client sent

What the interwebs are complaining about is that the
"hash(username + password)" piece that's stored in pg_authid is
sufficient to authenticate.

Here's what was proposed as an alternative which would prevent that
without breaking the existing wireline protocol:

client has username and password
server has user_salt,
N *
{salt, hash(hash(hash(username + password) + salt), user_salt)}

client:

send auth request w/ username and database

server:

picks random salt from the salts available for this user
sends salt to the user

client:

send hash(hash(username + password) + salt) to server

server:

server calculates, using the data from the client,
hash(FROM_CLIENT + user_salt)
compares to hash stored for salt chosen

This makes what is stored in pg_authid no longer directly useful for
authentication (similar to how Unix passwd-based authentication works)
because if the client sent any of those values, we'd add the user_salt
and hash it again and it wouldn't match what's stored.

This further makes what is sent over the network not directly
susceptible to a replay attack because the server has multiple values
available to pick for the salt to use and sends one at random to the
client, exactly how our current challenge/response replay-prevention
system works. The downside is that the number of possible values for
the server to send to prevent replay attacke is reduced from 2^32 to N.

To mitigate the replay risk we would, ideally, support a lock-out
mechanism. This won't help if the attacker has extended network access
though as we would almost certainly eventually go through all N
permutations for this user.

However, use of TLS would prevent the network-based attack vector.

Using TLS + the 'password' authentication mechanism would also achieve
the goal of making what is in pg_authid not directly useful for
authentication, but that would mean that the postmaster would see the
user's password (post-decryption), leading to a risk that the password
could be reused for access to other systems by a rogue server
administrator. Now, that's what SSH and *most* systems have had for
ages when it comes to password-based authentication and therefore it's
well understood in the industry and session-level encryption is
generally considered to avoid the network-based vector associated with
that approach.

For PG users, however, we encourage using md5 instead of password as we
consider that "better", but users familiar with SSH and other
unix-password based authentication mechanisms might, understandably,
think that MD5+TLS prevents both attack vectors, but it doesn't.
Password+TLS is what they would actually want to get the traditional
unix-password-style trade-offs.

Of course, the hashing algorithm used for all of the current
authentication systems we support is no longer generally considered
secure and that we use a non-random salt for storage (the username)
makes it worse.

Thanks!

Stephen

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Stefan Kaltenbrunner 2015-03-04 18:40:22 Re: MD5 authentication needs help
Previous Message Robert Haas 2015-03-04 18:10:24 Re: Normalizing units for postgresql.conf WAS: Patch: raise default for max_wal_segments to 1GB