You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by Scott Sanders <li...@jssjr.com> on 2008/01/31 16:36:46 UTC

Possible bug in apr_dbd_mysql

Hi,

After much frustration I was able to get apr_dbd_mysql compiled and working
on my machine. However, when testing the module I believe I stumbled across
a nasty little bug. My user database was originally designed to store user
passwords as md5 hashes and not the base64 encoded SHA1 digest. To remedy
this I created a new column int he user table called pwd2 and  modified my
login routine to populate this column with the encrypted format apache's
basic auth is expecting. This requires everyone to logout and log back in to
the system, of course, but in my environment that's OK. My initial apache
config to secure this section of the site with basic auth set the
AuthDBDUserPWQuery to "SELECT pwd2 FROM users WHERE email=%s AND active=1".
This worked and prevented invalid users (and inactive users) from
authenticating, but if the pwd2 field was empty then any password would
succeed. If pwd2 was NULL then the user was rejected, and if pwd2 had a
string in it the user was rejected (excepting, of course, when pwd2 had the
proper encrypted content).

This has got to be a bug in the apr_dbd_mysql code, but I unfortunately
don't have time right now to track it down and provide a patch. To solve my
problem I changed my query to "SELECT pwd2 FROM users WHERE email=%s AND
active=1 AND pwd2 !=''" but this is an ugly hack. Where is the bugzilla to
file this?

-Scott

Re: Possible bug in apr_dbd_mysql

Posted by Scott Sanders <li...@jssjr.com>.
On 2/2/08, Tom Donovan <do...@bellatlantic.net> wrote:
> Scott Sanders wrote:
> >     Scott Sanders wrote:
>
> >      > the pwd2 field was empty then any password would succeed. If pwd2 was
> >      > NULL then the user was rejected, and if pwd2 had a string in it
> >     the user
> >      > was rejected (excepting, of course, when pwd2 had the proper
> >     encrypted
> >      > content).
> >
> > I am able to reproduce this bug on another machine. Apache 2.2.8, MySQL
> > 5.0.22, APR 1.2.12, APR-Util 1.2.12 installed on CentOS 5 x86. Test
> > table and data created with:
> ...
> >
> > Having an empty password is perfectly valid, however, the bug is that as
> > long as the user is valid (i.e. the AuthDBDUserPWQuery doesn't return an
> > empty set) and the password field in the database is empty, any password
> > will authenticate the user.
>
> You are right.  Testing on Debian 4.0 shows that the Linux crypt(password, salt) function always
> returns an empty string whenever the salt argument is an empty string, regardless of the password.
> If your password hash is an empty string, then as you observed - any password will work on Linux.
>
> The crypt docs are at  http://www.gnu.org/software/libc/manual/html_node/crypt.html
> They don't say anything about what to expect when the "salt" argument is empty.
>
> Note that this is not related to DBD.  An empty-string hash in a file (or in a dbm) behaves the same
> way. This is Linux crypt() behavior, not anything that Apache does.
>
> You could log a GNU/crypt bug if you want, but I doubt you will get any answer except:
>    "don't store an empty string as the password hash"
>
> > I admit I have not turned on debugging and traced into the problem yet.
> > Any tips on where to start looking would be appreciated.
>
> The call to crypt_r() is at srclib/apr-util/crypto/apr_md5.c line 711.
> The first two arguments to crypt_r() are 1) the user-entered password, and 2) the password hash
>
> -tom-
>

Tom,

Thanks for taking the time to offer an explanation for this. I have
posted to the GNU Crypto lists just in case this is a bug and not the
expected behavior.

-Scott

Re: Possible bug in apr_dbd_mysql

Posted by Tom Donovan <do...@bellatlantic.net>.
Scott Sanders wrote:
>     Scott Sanders wrote:

>      > the pwd2 field was empty then any password would succeed. If pwd2 was
>      > NULL then the user was rejected, and if pwd2 had a string in it
>     the user
>      > was rejected (excepting, of course, when pwd2 had the proper
>     encrypted
>      > content).
> 
> I am able to reproduce this bug on another machine. Apache 2.2.8, MySQL 
> 5.0.22, APR 1.2.12, APR-Util 1.2.12 installed on CentOS 5 x86. Test 
> table and data created with:
...
> 
> Having an empty password is perfectly valid, however, the bug is that as 
> long as the user is valid (i.e. the AuthDBDUserPWQuery doesn't return an 
> empty set) and the password field in the database is empty, any password 
> will authenticate the user.

You are right.  Testing on Debian 4.0 shows that the Linux crypt(password, salt) function always 
returns an empty string whenever the salt argument is an empty string, regardless of the password. 
If your password hash is an empty string, then as you observed - any password will work on Linux.

The crypt docs are at  http://www.gnu.org/software/libc/manual/html_node/crypt.html
They don't say anything about what to expect when the "salt" argument is empty.

Note that this is not related to DBD.  An empty-string hash in a file (or in a dbm) behaves the same 
way. This is Linux crypt() behavior, not anything that Apache does.

You could log a GNU/crypt bug if you want, but I doubt you will get any answer except:
   "don't store an empty string as the password hash"

> I admit I have not turned on debugging and traced into the problem yet. 
> Any tips on where to start looking would be appreciated.

The call to crypt_r() is at srclib/apr-util/crypto/apr_md5.c line 711.
The first two arguments to crypt_r() are 1) the user-entered password, and 2) the password hash

-tom-

Re: Possible bug in apr_dbd_mysql

Posted by Scott Sanders <li...@jssjr.com>.
On 1/31/08, Tom Donovan <do...@bellatlantic.net> wrote:
>
> Scott Sanders wrote:
> > Hi,
> >
> > After much frustration I was able to get apr_dbd_mysql compiled and
> > working on my machine. However, when testing the module I believe I
> ...
> > but in my environment that's OK. My initial apache config to secure this
> > section of the site with basic auth set the AuthDBDUserPWQuery to
> > "SELECT pwd2 FROM users WHERE email=%s AND active=1". This worked and
> > prevented invalid users (and inactive users) from authenticating, but if
> > the pwd2 field was empty then any password would succeed. If pwd2 was
> > NULL then the user was rejected, and if pwd2 had a string in it the user
> > was rejected (excepting, of course, when pwd2 had the proper encrypted
> > content).
>
> I find that only an empty password works when AuthDBDUserPWQuery retrieves
> a value of ''.  Entering
> a non-empty password (in Firefox) gives a "Password Mismatch" error.  I'm
> using Apache 2.2.8 on Windows.


I am able to reproduce this bug on another machine. Apache 2.2.8, MySQL
5.0.22, APR 1.2.12, APR-Util 1.2.12 installed on CentOS 5 x86. Test table
and data created with:

CREATE TABLE accounts (
id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
user VARCHAR(64),
pass VARCHAR(64) NOT NULL);

INSERT INTO accounts (user) VALUES ('scott');

This results in a 'SELECT * FROM accounts' returning:

+----+-------+------+
| id | user  | pass |
+----+-------+------+
|  1 | scott |      |
+----+-------+------+


> This has got to be a bug in the apr_dbd_mysql code, but I unfortunately
> > don't have time right now to track it down and provide a patch. To solve
>
> Not really.  An empty string is not prohibited as a password unless you
> prohibit it.
> An empty-string is also the valid hash of an empty-string password.
>
> On Windows, BEOS, and Netware - plain-text passwords are used if there is
> no prefix.
> '' is a valid plain-text password.
>
> On Linux, crypt is used if there is no prefix.
>
>    hash = crypt_r(password, salt, buffer)
>
> returns an empty-string as the hash when called with an empty-string
> password and an empty-string
> salt.  I expect most other Unix systems do the same.


Having an empty password is perfectly valid, however, the bug is that as
long as the user is valid (i.e. the AuthDBDUserPWQuery doesn't return an
empty set) and the password field in the database is empty, any password
will authenticate the user.

To show this, I set up apache's default config and used a config like
follows (note that this dir is my docroot):

DBDriver mysql
DBDParams "dbname=test,user=root,pass=password"

DBDMin  1
DBDKeep 2
DBDMax  10
DBDExptime 60

<Directory "/home/ssanders/dev/apr_dbd_mysql-bug_proof/local/http/htdocs">
    Options Indexes FollowSymLinks

    AllowOverride None

    Order allow,deny
    Allow from all
  AuthType Basic
  AuthName "Company RSS Feed"
  AuthBasicProvider dbd
  AuthzUserAuthoritative On

  AuthDBDUserPWQuery "SELECT pass FROM accounts WHERE user=%s"
  Require valid-user
</Directory>

After starting apache, access the server, and attempt to auth using the user
scott and any password you choose; it will succeed and you will be taken to
the "It works!" page.

> my problem I changed my query to "SELECT pwd2 FROM users WHERE email=%s
> > AND active=1 AND pwd2 !=''" but this is an ugly hack. Where is the
> > bugzilla to file this?
>
> It doesn't seem ugly to me.  If you insist on storing '' in pwd2, yet you
> don't want it treated as a
> valid password; then enforcing your rule in SQL seems reasonable.
>
> Existing sites may already use an empty-string password when they want the
> user to voluntarily enter
> a (valid) username but they don't require any password to verify it.  Not
> the usual case, but it
> doesn't seem necessary to break their scheme just to allow for storing
> empty passwords and then
> denying them.  As you pointed out, storing a NULL as the password hash
> will always reject a login
> attempt.
>
> -tom-


I admit I have not turned on debugging and traced into the problem yet. Any
tips on where to start looking would be appreciated.

-Scott

Re: Possible bug in apr_dbd_mysql

Posted by Tom Donovan <do...@bellatlantic.net>.
Scott Sanders wrote:
> Hi,
> 
> After much frustration I was able to get apr_dbd_mysql compiled and 
> working on my machine. However, when testing the module I believe I 
...
> but in my environment that's OK. My initial apache config to secure this 
> section of the site with basic auth set the AuthDBDUserPWQuery to 
> "SELECT pwd2 FROM users WHERE email=%s AND active=1". This worked and 
> prevented invalid users (and inactive users) from authenticating, but if 
> the pwd2 field was empty then any password would succeed. If pwd2 was 
> NULL then the user was rejected, and if pwd2 had a string in it the user 
> was rejected (excepting, of course, when pwd2 had the proper encrypted 
> content).

I find that only an empty password works when AuthDBDUserPWQuery retrieves a value of ''.  Entering 
a non-empty password (in Firefox) gives a "Password Mismatch" error.  I'm using Apache 2.2.8 on Windows.

> This has got to be a bug in the apr_dbd_mysql code, but I unfortunately 
> don't have time right now to track it down and provide a patch. To solve 

Not really.  An empty string is not prohibited as a password unless you prohibit it.
An empty-string is also the valid hash of an empty-string password.

On Windows, BEOS, and Netware - plain-text passwords are used if there is no prefix.
'' is a valid plain-text password.

On Linux, crypt is used if there is no prefix.

   hash = crypt_r(password, salt, buffer)

returns an empty-string as the hash when called with an empty-string password and an empty-string 
salt.  I expect most other Unix systems do the same.

> my problem I changed my query to "SELECT pwd2 FROM users WHERE email=%s 
> AND active=1 AND pwd2 !=''" but this is an ugly hack. Where is the 
> bugzilla to file this?

It doesn't seem ugly to me.  If you insist on storing '' in pwd2, yet you don't want it treated as a 
valid password; then enforcing your rule in SQL seems reasonable.

Existing sites may already use an empty-string password when they want the user to voluntarily enter 
a (valid) username but they don't require any password to verify it.  Not the usual case, but it 
doesn't seem necessary to break their scheme just to allow for storing empty passwords and then 
denying them.  As you pointed out, storing a NULL as the password hash will always reject a login 
attempt.

-tom-




Re: Possible bug in apr_dbd_mysql

Posted by Bojan Smojver <bo...@rexursive.com>.
On Thu, 2008-01-31 at 10:36 -0500, Scott Sanders wrote:
>  AuthDBDUserPWQuery to "SELECT pwd2 FROM users WHERE email=%s AND
> active=1".

It is Apache's mod_authn_dbd that does the above.

> This has got to be a bug in the apr_dbd_mysql code

Could be. It could also be something to do with mod_authn_dbd. Did you
try to run the Apache process through GDB to see what actually makes
authentication succeed?

-- 
Bojan