Re: [phplib] Newbie security query From: John Sutton (john <email protected>)
Date: 09/07/00

On Wed, 06 Sep 2000, you wrote:
> John Sutton wrote:
>
> > I'm using php3 + phplib for a number of sites on a web server which I control.
> > I would like to improve the security of the setup. The problem I have is the
> > existence of a cleartext mysql password in each customer's local.inc file!
> >
>
> I've had some thoughts about this issue, and I think I've got the solution
> (although it isn't implemented yet). My proposal is to use Apache's own
> configuration file to store usernames/password of databases. This would have to be
> done with a helper module that implements a way to retrieve some data from the
> configuration and store them in the Apache notes system. Since 'httpd.conf' would
> be only root-readable, normal users wouldn't be able to read the data, and php code
> would read them through "apache_note()". It's main drawback is that any module
> could read the passwords from Apache, but anyway, those modules could read .php
> files as well; and this scheme is only suitable to Apache.

I don't know anything about the "Apache notes system". When you say that "any
module could read the passwords from Apache" do you mean that a user could
write non-privileged code which (through using some module or another) could
access this information? If so, it's no good for the purpose I've outlined
below.

> Another way, is that PHP itself reads a special file (only root-readable) containg
> the passwords at startup time (when the web server is booting up in root mode), and
> provide them to the scripts when they call a function with a secret code (something
> like a password's password). When an evil user browses the php files, they would
> be able only to know this secret code, and not the password itself (and this secret
> code would be useless to this evil user because he couldn't modify the php files).
> This is the generalization on the previous apache-notes way.

But what is to prevent the evil user from writing a PHP script which calls the
function using the same secret code? This comes down to: how can the function
know the "identity" of the caller, because by default all callers have the same
identity!

IHMO, for this kind of scheme to work, the following has to be true:

1) there must exist a root-only readable list (flatfile, gdbm file, whatever)
which associates each unix uid with corrresponding mysqluids/passwords which
that unix user is allowed to use.

2) there has to be a function within PHP which when called finds the owner of
the calling script (i.e. stats $PHP_SELF) and uses this to lookup the mysql
auth info for that unix uid in the list (in 1 above).

How can this lookup be performed? Either the list is already held by the
apache daemon (as per your first idea above) or an external root setuid is
called to access the list. Either way, the function (in 2 above) must be an
*internal* PHP function because it needs access to privileged information i.e.,
either the list itself (held internally), or some secret which it passes to the
external root setuid so that the latter can validate that it is being called
legitimately.

I would favour holding the list externally (in a gdbm file or simple flat
text file for example) simply so that you don't have to restart apache every
time you want to modify the list. So, if all this is correct (!), we need the
following:

1) a modification of the modphp initialisation code (which I'm presuming
exists? i.e. code that runs on apache startup and runs with root uid) to
generate a random secret which is stored in a root-owned mode 400 file called
(say) /etc/httpd/conf/mysqlpasswd.key AND which is also stored somewhere in
shared memory accessible only to (all instances of) modphp. (Err, is this
latter possible??? A piece of memory only accessible to apache children? And
only accessible by the php module i.e. there must be no way to expose this info
by tickling other modules, even if in principle those other modules could
access it.)

2) a internal PHP function which does this:

i) stats $PHP_SELF to get the owner of the current script
ii) generates a random string and an md5 hash of this string with the random
secret which it retrieves from the shared memory
iii) calls the external root setuid helper program with 3 arguments: the owner
uid, the random string and the md5 hash
iv) returns the array of triplets - databasename:username:password - which are
returned to it by the helper.

3) an external root setuid helper program which does this:

i) validates the call by reading /etc/httpd/conf/mysqlpasswd.key and hashing it
with the passed random string arg. If the result matches the passed hash arg,
it's a valid call.
ii) used the passed unix uid arg to retrieve the associated triplets from a
text or gdbm file (which of course is root-owned mode 400)
iii) return the triplets on standard output.

Does it make sense? If so, and somebody knows how to do 1 & 2, I'll
write the helper program (yes, I know that's the easy bit ;-)

> PHP developers, are you listening?

I think you omitted to send your email to the list and sent it to me only?

***************************************************
John Sutton
SCL Computer Services
URL http://www.scl.co.uk/
Tel. +44 (0) 1239 621021
***************************************************

---------------------------------------------------------------------
To unsubscribe, e-mail: phplib-unsubscribe <email protected>
For additional commands, e-mail: phplib-help <email protected>