On 10/2/07, The Anarcat <..hidden..> wrote:
Just to make things clearer, you have a few ways of doing auth:
1. Client-side based solution (HTTP Auth, cookies, GET...)
2. Server-side based solution (sessions)
In those approaches, from what I understand, the username/password is
stored "somewhere" and communicated back to the postgresql server at
every request. I assume there's no other way around that.
I would agree with the above assessment with the following caveat: That ways around the above limitation are not generally applicable (for example, Kerberos tickets).
Approach 1
----------
Approach 1 is the HTTP Auth, Cookies or GET solution, which is pretty
much the same thing: challenge the client, which provides the
username/password back, *at every hit*.
Note that being able to do things like X.509 and Kerberos auth would both require this procedure. I don't know if there is a way of authenticating to PostgreSQL using
X.509 client certs (for actual user auth), but even if it is not possible at the moment, I am sure that it would be possible to hire someone to make either a PAM module or a direct auth method in PostgreSQL).
There are way to mitigate the security issues surrounding that approach.
One that I can think of real quick is to *encrypt* the password using a
server-side token that is stored in a sessions table. When the user
sends its credentials in the first time, it gets encrypted and is sent
back (through GET or cookies). Everytime the user comes back, that
password is decrypted and channeled through pgsql. The encrypted
password is nevery stored in the database, but will fly all around the
place, over hopefelly SSL-secured connections.
I think we should separate the issues of storage and transmission. The password is always stored at some point in browser memory in plain text (for example, when it is entered). It is always submitted to the server in plain text in the initial login in all of these cases. So the question is, where is the window of risk and how do we mitigte it.
This workaround of course doesn't really work with HTTP Auth, although
the non-Basic HTTP Auth mecanisms have a similar feature.
It wouldn't work with HTTP auth and our general agreements on where and when to degrade _javascript_, and would in that case, limit drastically the number of supported browsers.
There are also _javascript_-based encryption scheme that can do similar
tricks. The SPIP CMS is a good example of how to do that.
Approach 2
----------
Approach 2 is the other way around. We only communicate a session to the
user (a bit the way PHP sessions work) and store whatever credentials we
want in a server-side session table. Notice how this differs from the
above in that the credentials are explicitely stored in a ledger
database/session table.
First, I am not sure that session storage on number poses any inherent security advantage over cleint management. In both cases, the initial password is sent to the server in the clear, so if someone can evesdrop on that initial login request, they can sniff the password. The question is whether there is additional risk in resubmitting the password multiple times.
On a non-switched network (with hubs only), someone can run a sniffer program without being detected for an extended time period. In this case, you can get the login credentials as soon as someone logs in over an unprotected connection (
i.e. no SSL). Hence there is no additional risk in this case for submitting the password on every request unless you are a real gambler.
On a switched network, there is also a case to be made that this isn't an additional problem. Sniffing across switches requires ARP mirroring which can be detected fairly quickly if you are looking for it. Note that this reqires mirroring the ARP request on *every* ARP request and hence you can't target just HTTP requests. Although this does reduce the signature, it does not do so beyond the point where it would be easily detectable.
So, I think that the solution is to document that SSL should *always* be used to communicate with the web server (communicating with PostgreSQL is a different story since you could use MD5 auth for that leg). This is especially necessary since
1.3 will have reasonably effective security measures in place.
So I am not sure that it is a problem to send the passwords in the clear over the network connection on every request since we have to do that anyway. We just need to document that the network connection must be protected with SSL, IPSec, SSH, or the like.
Conclusion
----------
I think that it really depends on where you put your trust. Keep
passwords on the client or server side? Note that you don't have to keep
it in clear text anywhere, as both can use tokens to encrypt (and then
decrypt) the credentials.
The big advantage to using HTTP Auth is that security issues with session password storage are no longer our responsibility (though of course, they would still be somethng we would want to address if they come up).
We're basically stuck with those two approaches because of the way the
web works (ie. no built-in client-side session system). Note that we
*could* keep the pgsql passwords in-memory if we would use mod_perl or
similar, but that would just be another way of putting approach 2...
Here is what I was thinking:
On each submission, we get HTTP Auth credentials and a session id from a cookie. We can use that session id to time out existing logins, We handle this by destroying cookies appropriately and requesting authentication when the cookie is invalid. Hence to log in you must provide a valid username and password. To do anything of consequence, you must provide a valid username, password, and session id. To use the application in a secure environment you must protect your network connections appropriately (ESP, SSL, SSH, or the like).
If a browser is found to be insecure, we can add its user agent string to a blacklist if we need to.
Best WIshes,
Chris Travers