Thanks Evan, that's a new word I didn't know about, 'nonce'.
Let me see if I got your objection right and may answer it. The
session_id() is no secret, the server sends it to the client. The client
cannot and does not send the session_id() used to hash the password back to
the server, it does not need to, the client got it from the server.
It is the server that challenges the client with a session_id() (or any
other random) sent clear and the client has to take the challenge and
combine it with the password (which is not transmitted clear). Thus the
client cannot tell the server, 'this is user xxx, with password yyyy hashed
under session_id zzzz'. It is the server that challenges the client with
the session_id. The attacker might collect enough samples so if a challenge
repeats, he can have the answer ready, but that is unlikely with long enough
challenges (and session_ids are long).
As for sending the session_id() from the server to the client in clear (not
encrypted) it seems to me it doesn't make any sense to alter it in any way
since, after all, you are also sending the algorithm in Javascript to the
client, which is clear for anyone to see, so there would be no point in
trying to hide the session_id in any way, and I don't think it would help
the overall security.
My bank does use SSL, of course, and it still requires confirmation to do
critical processes so, that might be a partial solution to spoofing.
Anyway, this is a poor man replacement for SSL, with limitations, but it is
good to know what are those limitations.
Thanks for your help
Satyam
----- Original Message -----
From: "Evan Priestley" <spam@xxxxxxxx>
To: "Satyam" <Satyam@xxxxxxxxxxxxx>
Cc: <php-general@xxxxxxxxxxxxx>
Sent: Monday, March 27, 2006 5:41 PM
Subject: Re: protecting passwords when SSL is not available
This is called a "nonce"[1], and the method you've described will give
you marginally less awful security than submitting a plaintext password
or an unadulterated hash of the password, but, obviously, is in no way a
substitute for real SSL. For instance, if this password puts the session
in a "logged in" state, an attacker with the capacity to sniff the
password can also sniff the "logged in" session ID after authentication.
You can potentially bind the login to IP, but will prevent users behind
rotating proxies from using your service and may not protect users behind
non-rotating proxies, and the source IP for a request can be spoofed.
Alternatively, you can require the password for any action requiring
authorization (and never put the user in a "logged in" state), but this
will impose substantial constraints on your design. And, of course, an
attacker can still observe any other data you transmit.
If you implement nonced password transmission, absolutely ensure that an
attacker can not alter the provided nonce. For instance, if Bob sees
Alice log in under nonce "abc123" (her PHP session ID), what happens if
Bob later executes a replay attack by mimicking her form submission
(username: alice, password_hash: def456, session_id: abc123)? If he can
gain access via replay attack at any time after Alice's first login ([a]
while her session is valid or [b] after it has expired presumably being
the critical periods), the system offers no security over non-nonced
password transmission.
Evan
[1] http://en.wikipedia.org/wiki/Nonce
On Mar 27, 2006, at 8:30 AM, Satyam wrote:
I know the answer to a secure site is SSL, but what if you are on a
shared host, SSL is unavailable and you still want some sort of
security?
This is what I came by and I would appreciate any advice as to possible
security holes in it. There is a big hole I know, which is the screen
to change the password, I find no way to secure that one. But lets go
to what I do have.
I found at http://pajhome.org.uk/crypt/md5/md5src.html a Javascript
version of the MD5 algorithm.
I checked it against the PHP md5() function:
<html><head><title>MD5 test</title>
<script language="JavaScript" src="includes/md5.js"></script>
<script>
function enOnLoad() {
document.getElementById('prueba').innerHTML = md5_vm_test(); // test
provided by the library
<?php
$valor = rand();
?>
document.getElementById('p2').innerHTML = hex_md5('<?=$valor?>');
}
</script>
</head><body onLoad="enOnLoad();">
<div id=prueba></div>
<div id=p2></div>
<div><?=md5($valor)?></div>
</body></html>
And the results of the Javascript and the PHP md5() functions are the
same (the JS source has a couple of parameters to play with, but the
defaults proved good enough)
So, my idea is that in the login script, PHP will send a random number
along with the login form. That random might actually be the
session_id() but if not, the random value sent has to be stored in a
session variable. (I really don't see any reason not to use the
session_id()).
On clicking on submit to send the login form, the password field would
be replaced by the result of
a) calculate the MD5() of the password, trimmed of whitespace. This
should be the same value stored in the user table of the database.
b) concatenate this value with the random number (or session_id())
provided by the server.
c) calculate the MD5() of this
d) replace it into the original password field and let the submit
proceed.
On the server side, when the login data is received:
a) retrieve the password field from the user table on the database.
This should actually be the MD5-encripted of the actual password.
b) concatenate this value with the session_id() or whatever random you
generated before
c) calculate the MD5() of this
d) compare with received value. If they match, they come from the same
password.
Would it work?
Satyam
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php