Encryption Question

B

Bart Van der Donck

yes I fear that this is NOT secure. Take for instance the
condition that the user knows the previous password.

It's the same as saying that the application can trust the user.
Anyone who knows the previous password, may change it to a new one.
The old password is stored in the mysql database as SHA1
hash. (let us say for argument's sake the old password was
'fred' and that the new is 'newpassword' so the database
contains the sha1 hash
$db_data = sha1('fred')
now the user typed in fred which with a salt was sha1'd by
the client and sent to the server.
js-> sha1(salt+sha1('fred'))
then sends this as hashed_data
the server must check that the user entered fred, but can
only do this by copying the procedure server-> sha1($salt .
$db_data ) and seeing if it is equal to what was
in the $_POST var $_POST['hashed_data'].

In my scheme, the server doesn't know anything about the plaintext
password because nothing plaintext is sent from js or received at
server. All it gets is the already js-hashed string to do stuff with.
The server doesn't do any hashing, all it does is compare the hashed
string to what's stored.

- user types current password
- js hashes it (irreversibly)
- js sends only hash to server, not plaintext (yes, over HTTPS)
- server compares if it matches to its own stored (hashed) string
- if it matches, authentication succeeded (so he can enter application
or change password etc.)

I don't see a leak in this scheme, but, please, I'ld be very happy to
know, I'm running a whole university based on this :)
Now what you are proposing is that the server checks this
and when the user has indeed verified that they know the old
password, you then _replace the old hash with sha1('newpassword')

Yes, with sha1('newpassword') encrypted by javascript.
now anyone listening to the traffic as Richard says now knows
the new hash they have eaves dropped sha1('newpassword')

You're right, but that's why the traffic should go over HTTPS. Then
this can't happen.
so the attacker just requests the logon page, gets given a
new salt and can now send this POST data (using some proxy or
other or a header editor)
$_POST['hashed_data'] = sha1( newsalt+sha1('newpassword') )
the attacker doesnt need to know the password.

Okay, but he does need to know the hashed string. I don't see how he
can get that information if the traffic goes over HTTPS.
The server accepts this and compares it against the database
entry by the smae method as before
server-> sha1($newsalt . $new_db_data )
where $new_db_data is sha1('newpassword')
they match and the attacker gets in

Yes he's in then, but he must always know the hashed password for
that. Sure, if that is known, one can get in. But I don't see how an
attacker could get his hands on it, assumed that the traffic goes over
HTTPS.
 
S

shimmyshack

shimmyshack said:
On 14 Mar, 22:21, "Richard Cornford" wrote:
yes I fear that this is NOT secure. Take for instance the
condition that the user knows the previous password.

It's the same as saying that the application can trust the user.
Anyone who knows the previous password, may change it to a new one.
The old password is stored in the mysql database as SHA1
hash. (let us say for argument's sake the old password was
'fred' and that the new is 'newpassword' so the database
contains the sha1 hash
$db_data = sha1('fred')
now the user typed in fred which with a salt was sha1'd by
the client and sent to the server.
js-> sha1(salt+sha1('fred'))
then sends this as hashed_data
the server must check that the user entered fred, but can
only do this by copying the procedure server-> sha1($salt .
$db_data ) and seeing if it is equal to what was
in the $_POST var $_POST['hashed_data'].

In my scheme, the server doesn't know anything about the plaintext
password because nothing plaintext is sent from js or received at
server. All it gets is the already js-hashed string to do stuff with.
The server doesn't do any hashing, all it does is compare the hashed
string to what's stored.

- user types current password
- js hashes it (irreversibly)
- js sends only hash to server, not plaintext (yes, over HTTPS)
- server compares if it matches to its own stored (hashed) string
- if it matches, authentication succeeded (so he can enter application
or change password etc.)

I don't see a leak in this scheme, but, please, I'ld be very happy to
know, I'm running a whole university based on this :)
Now what you are proposing is that the server checks this
and when the user has indeed verified that they know the old
password, you then _replace the old hash with sha1('newpassword')

Yes, with sha1('newpassword') encrypted by javascript.
now anyone listening to the traffic as Richard says now knows
the new hash they have eaves dropped sha1('newpassword')

You're right, but that's why the traffic should go over HTTPS. Then
this can't happen.
so the attacker just requests the logon page, gets given a
new salt and can now send this POST data (using some proxy or
other or a header editor)
$_POST['hashed_data'] = sha1( newsalt+sha1('newpassword') )
the attacker doesnt need to know the password.

Okay, but he does need to know the hashed string. I don't see how he
can get that information if the traffic goes over HTTPS.
The server accepts this and compares it against the database
entry by the smae method as before
server-> sha1($newsalt . $new_db_data )
where $new_db_data is sha1('newpassword')
they match and the attacker gets in

Yes he's in then, but he must always know the hashed password for
that. Sure, if that is known, one can get in. But I don't see how an
attacker could get his hands on it, assumed that the traffic goes over
HTTPS.

Sure Bart, my bad, I didn't understand your previous posts probably :)
- yes HTTPS *must* be used to send the *new* password hashed or not.
Then your scheme is FINE! Your university is safe - on a few
conditions!
The OP doesn't appear to have SSL and so I wanted to make sure that he
knew that without SSL you cannot either set a new password, or change
a password without SSL using irreversible hashes without revealing
enough info to passive or active sniffers to compromise the exchange -
although here even I am prepared for someone cleverer than me - there
are many of them - to show me how!!

The conditions I refer to are "nowhere on that domain/site can there
be an XSS vulnerability". SSL cannot help you then, as the javascript
hash can be stolen before/after it is sent via HTTPS, this is the
situation with most websites from time to time; for instance there is
a google.com XSS doing the rounds at the moment, which allows stuff to
be stolen from within the application, it doesnt care how the
transport is made, once that javascript makes its way inside the app
it acts when in the browser.
Yeah Bart, I agree, using HTTPS to send the hashed new password as a
POST payload is shall we say "safest".
Man, the OP must wish he never asked!
 
B

Bart Van der Donck

Richard said:
Isn't the problem with sending the password in plain text
over HTTP that someone may intercept the traffic and so
acquire the password for later use in gaining access that
they are not entitled to?
Precisely.

However, if a 'hash' of the password is sent in plain text
over HTTP, and all the server knows is the 'hash' of the
password, has the situation really changed?

No. It's the programmer's choice to let the client perform the
encryption in this scenario. Sure, one could send the password in
plaintext too, and let server encrypt it. This would be a more
traditional approach, and, as long as it uses HTTPS, an equally secure
scheme.
What is to stop someone who knows the 'hash' of the
password inserting it into the appropriate location in an
HTTP request (by any of numerous means, including the
executing of alien javascript on the logon page)? Wouldn't
the server recognise the intercepted 'hash' as easily as
it may have recognised the original password?
Yes.

The advantage of HTTPS is that someone intercepting the
HTTP traffic is not going to find it easy to make any
sense of what they observe.

Understatement - HTTPS is secure. But its importance should not be
exaggerated and well scoped. HTTPS does not take care of your safety;
it only secures the transmission itself (cfr. its "tunnel"-
terminology) which is only a small part of the total security picture
of an application.

Shimmyshack is very right to state that most of the troubles aren't
caused by not applying HTTPS, but by what happens after the sensitive
data has arrived at the server. After all, traffic can only be
intercepted at each hop from client to server, and, apart from the W/
LAN, these hops are ISP's routers that are mostly strictly secured.

Tons of sensitive data travel unencrypted this way: POP3 for email,
default UNIX (htaccess) authentication, passwords of internet
subscriptions, FTP, Telnet passwords, (XML) message sets, etc.
 
S

shimmyshack

No. It's the programmer's choice to let the client perform the
encryption in this scenario. Sure, one could send the password in
plaintext too, and let server encrypt it. This would be a more
traditional approach, and, as long as it uses HTTPS, an equally secure
scheme.


Understatement - HTTPS is secure. But its importance should not be
exaggerated and well scoped. HTTPS does not take care of your safety;
it only secures the transmission itself (cfr. its "tunnel"-
terminology) which is only a small part of the total security picture
of an application.

Shimmyshack is very right to state that most of the troubles aren't
caused by not applying HTTPS, but by what happens after the sensitive
data has arrived at the server. After all, traffic can only be
intercepted at each hop from client to server, and, apart from the W/
LAN, these hops are ISP's routers that are mostly strictly secured.

Tons of sensitive data travel unencrypted this way: POP3 for email,
default UNIX (htaccess) authentication, passwords of internet
subscriptions, FTP, Telnet passwords, (XML) message sets, etc.

Then there's the problem of the big-brother IT dept. that installs pre-
trusted certs onto PCs, so they can proxy the SSL, de/re-encrypting it
at the border!
 
R

Richard Cornford

Bart said:
No. It's the programmer's choice to let the client perform
the encryption in this scenario. Sure, one could send the
password in plaintext too, and let server encrypt it. This
would be a more traditional approach, and, as long as it
uses HTTPS, an equally secure scheme.
<snip>

If we accept that HTTPS is providing a secure tunnel for transmission of
the password information from the client to the server and so eliminating
the risk of interception we have two points where the password
information can be picked up. At the client (which we cannot do much
about in most cases) and at the server. You have suggested that it is not
a good idea for the passwords to be stored in plain text on the server. I
would agree with that; someone seeing the password on the server could
easily go to a client and enter that password and be logged on with the
privileges granted to that password (assuming that they also know the
user name in question). So the value stored on the server is the
post-hash equivalent of the password.

However, if you hash on client prior to transmission and compare what
arrives with the stored hashed version don't you now have the problem
that someone seeing the hashed version on the server can take that and
insert it on the client at the point where the client side hashing
outputs, pump it into our 'safe' HTTPS tunnel and have it recognised when
it comes out of the other end? While if the hashing is done on the
server, and it is the password text that is transmitted, seeing the
post-hash version on the server will not tell someone what password text
they could be inserting on the client, and the only point where they
could insert the post-hash version to gain access is in the code that
does the password verification on the server. And if they can get at (and
influence) that code they don't actually need to know any passwords at
all.

Richard.
 
S

shimmyshack

<snip>

If we accept that HTTPS is providing a secure tunnel for transmission of
the password information from the client to the server and so eliminating
the risk of interception we have two points where the password
information can be picked up. At the client (which we cannot do much
about in most cases) and at the server. You have suggested that it is not
a good idea for the passwords to be stored in plain text on the server. I
would agree with that; someone seeing the password on the server could
easily go to a client and enter that password and be logged on with the
privileges granted to that password (assuming that they also know the
user name in question). So the value stored on the server is the
post-hash equivalent of the password.

However, if you hash on client prior to transmission and compare what
arrives with the stored hashed version don't you now have the problem
that someone seeing the hashed version on the server can take that and
insert it on the client at the point where the client side hashing
outputs, pump it into our 'safe' HTTPS tunnel and have it recognised when
it comes out of the other end? While if the hashing is done on the
server, and it is the password text that is transmitted, seeing the
post-hash version on the server will not tell someone what password text
they could be inserting on the client, and the only point where they
could insert the post-hash version to gain access is in the code that
does the password verification on the server. And if they can get at (and
influence) that code they don't actually need to know any passwords at
all.

Richard.

yes, that is the problem of a "password equivalent" just using a hash
sent from client and comparing with has on server, so the javascript
routine does a hash of the (password+seed)
where the seed is sent by the server along with the form,
this is actually what gets sent.
the server knows what seed it sent which it stores as a session,
when it receives the hash(password+seed)
it performs the same thing server side and finding the results are the
same means its ok. and immediately expired the seed from the session
so if the traffis /is/ somehow intercepted and played back, the server
no longer knows the seed meaning it cannot perform hash(password+seed)

However you are thinking but how can the server do hash(password+seed)
when it doesnt have the plaintext password in teh database, right! It
can only do hash( db_hash_password+seed) where db_hashed_password is
the prehashed form of the plaintext password that /is/ stored in the
database.

so the javascript client must hash twice first to get the hashed form
of the password, and then adding the seed and hashing that.

hash( hash(password)+seed )
it is /this/ that the server then does.

eliminating the replay attack using the seed, and never needing to
know the plaintext on the server.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,198
Latest member
JaimieWan8

Latest Threads

Top