Re: how to properly secure non-ssl logins (php + ajax)

2009-02-20 Thread Ivan Krstić

On Feb 15, 2009, at 7:30 AM, Rene Veerman wrote:
Recently, on both the jQuery(.com) and PHP mailinglists, a question  
has arisen on how to properly secure a login form for a non-ssl web- 
application.


What's the threat model?

users[user_id].user_login_hash = onewayHash(user_login_name +  
preferences.pref_system_hash);


That you're hashing the username suggests you're worried about  
eavesdroppers identifying the user at login time. But without SSL,  
it'll almost certainly be trivial for an eavesdropper to identify the  
user _after_ they login. What's the threat model?


//checks since when [browser IP] has last received a new challenge,  
if < threshold : make a new challenge. else return old challenge.


It is incorrect to rely on a bijection between IPs and users.


"preferences.pref_system_hash">


What you're calling a system hash is usually referred to as salt.


// walk through all the records in users table, for each, calculate:


This is a completely broken approach, and prohibitive for applications  
with more than a handful of users.


I suggest you start by trying to write down a clear, brief and  
coherent threat model. Once that's done, you can solicit feedback  
until you're satisfied with the definition of what you're trying to  
build. Once you can focus on implementation, I suggest looking at  
things like bcrypt, PBKDF2, and SRP as background reading.


Cheers,

--
Ivan Krstić  | http://radian.org

-
The Cryptography Mailing List
Unsubscribe by sending "unsubscribe cryptography" to majord...@metzdowd.com


Re: how to properly secure non-ssl logins (php + ajax)

2009-02-20 Thread Erwan Legrand
Hi,

> Recently, on both the jQuery(.com) and PHP mailinglists, a question has
> arisen on how to properly secure a login form for a non-ssl web-application.
> But the replies have been "get ssl".. :(

What makes you think these are ill-advised?

> I disagree, and think that with a proper layout of authentication
> architecture, one can really secure a login system without having the
> administrative overhead of installing SSL everywhere, and the monetary cost
> for a SSL certificate for each domain.

Well, it depends on how much security is enough for you. If the
threats you are concerned with encompass the threats mitigated by
SSL/TLS, then you should definitely use TLS. You could arguably use
Kerberos, SSH or IPSEC to achieve the same level of security, but that
would not be handy, since SSL/TLS is what is bundled in web servers
and browsers. Oh, and you don't necessarily have to buy a certificate
to Verisign to use SSL!

The only thing your scheme seems to achieve is protect your password
against eavesdroppers. But then, an eavesdropper could reuse your
cookie to hijack your session. Your protocol does not mitigate such
threats as session hijacking, MITM, phishing, HTTP cache poisoning and
the list goes on. And whatever the shortcomings of TLS might be, it
does mitigate these threats.

Now, if you threat model goes along the lines of :
 * The only asset I want to protect is my password (because I use the
   same password to access critical data hosted on other services!)
 * I don't care whether my session is compromised.
 * I don't care whether my data is captured by an eavesdropper.
Then your scheme might indeed be what you need. I did not give it more
than a quick look though. And I would suggest you reconsider in the
first place the reasons that made you reuse such a precious password.

I hope this last paragraph makes sense and you will forgive my use of sarcasm.
--
Erwan Legrand

Simplicity is prerequisite for reliability.
   -- E. W. Dijkstra

-
The Cryptography Mailing List
Unsubscribe by sending "unsubscribe cryptography" to majord...@metzdowd.com


Re: how to properly secure non-ssl logins (php + ajax)

2009-02-20 Thread Lea Kissner
[Moderator's note: top posting is not considered good form. --Perry]

Hi Rene,

I suspect from reading this quickly that you may not be a cryptographer. I'd
highly suggest that you borrow one for a bit before you go ahead with this.
I'm having a bit of trouble reading exactly what you want to do, but I am
fairly sure that this isn't as secure as you'd like. (Heck, I can probably
help you out with this, but not today because I'm swamped.)

Thanks,
Lea

On Sun, Feb 15, 2009 at 4:30 AM, Rene Veerman  wrote:

> Hi.
>
> Recently, on both the jQuery(.com) and PHP mailinglists, a question has
> arisen on how to properly secure a login form for a non-ssl web-application.
> But the replies have been "get ssl".. :(
>
> I disagree, and think that with a proper layout of authentication
> architecture, one can really secure a login system without having the
> administrative overhead of installing SSL everywhere, and the monetary cost
> for a SSL certificate for each domain.
>
> I wish to code such a solution into a really-free library (so probably LGPL
> or GPL + MIT) over the next 2 to 5 months.
> This library would be a complete SQL, PHP & javascript package (jQuery
> "plugged in"), targetted for the novice programmer.
>
> I'm halfway (or more?) there, i think.
> For my own CMS, i have taken the following approach, which i'd like to hear
> your improvements on:
>
> (For onewayHash() i have MD5 and SHA256 implementations in both JS and
> PHP..)
>
>  SQL:
>
> create table users (
>  user_id   integer,
>  user_login_name  varchar(250),
>  user_login_hash  varchar(250),
>  user_password_hash   varchar(250),
> other fields
> primary key (user_id)
> );
>
> create table preferences (
>  pref_system_hash   varchar(250)
> 
> );
>
>  PHP (pseudo-code) , on system installation:
>   preferences.pref_system_hash = onewayHash ( randomStringLength(100) );
>
>  PHP , on user-create:
>
>  users[user_id].user_login_hash = onewayHash(user_login_name +
> preferences.pref_system_hash);
>  users[user_id].user_password_hash = onewayHash ("someGooodPasswordNot" +
> preferences.pref_system_hash);
>
>  PHP, on request of a login form:
>
>  challenge = makeNewChallenge ();
>   //checks since when [browser IP] has last received a new challenge,
> if < threshold : make a new challenge. else return old challenge.
>  //a challenge is a random string (+ special chars) pushed through the
> onewayHash function.
>
>  html = '
>  
>  value="preferences.pref_system_hash">
> 
> 
> 
> 
> 
>  
>   ';
>   sendHTMLtoBrowser (html);
>
>  Javascript: on page with login form:
>
>   jQuery('#loginForm').submit (function () {
> var sh = jQuery('#sh')[0]; //same for ch, plain_user, plain_pass,
> all the inputs in the html form.
> 
>
> user_hash = onewayHash ( onewayHash ( plain_user.value + sh.value )
> + challenge );
> //same for pass_hash basically
>
> plain_user.value = ''; //clear out the plain text fields so they
> dont get transmitted (same for plain_pass ofcourse)
>
> jQuery.ajax ( /* submit login form through POST, handle results */
> )
>   }
>
>
>  PHP, on receiving the login form data:
>
>  // walk through all the records in users table, for each, calculate:
> user_hash = onewayHash ( users[user_id].user_login_hash + challenge
> );
> pass_hash = onewayHash ( users[user_id].user_password_hash +
> challenge );
>
>  // if they match what was sent, then it's the user we're looking for
> with the right password, so their $_SESSION['authenticated_user'] = updated.
>
> 
>
>
> If you have a completely alternative way of securing a non-ssl login form,
> i'd like to hear about it too.
-
The Cryptography Mailing List
Unsubscribe by sending "unsubscribe cryptography" to majord...@metzdowd.com


Re: how to properly secure non-ssl logins (php + ajax)

2009-02-20 Thread Alexander Klimov
On Sun, 15 Feb 2009, Rene Veerman wrote:
> Recently, on both the jQuery(.com) and PHP mailinglists, a question has
> arisen on how to properly secure a login form for a non-ssl web-application.
> But the replies have been "get ssl".. :(

Unfortunately, they are right: get SSL.

> If you have a completely alternative way of securing a non-ssl login
> form, i'd like to hear about it too.

I suspect what you have coded is a reinvention of RFC 2617
(implemented, e.g., by mod_auth_digest in Apache).

Depending on your threat model, this can be all you need
(plaintext password is not transmitted, but this does not prevent
local dictionary attacks), but any such scheme fails miserable
against active attacks.

-- 
Regards,
ASK

-
The Cryptography Mailing List
Unsubscribe by sending "unsubscribe cryptography" to majord...@metzdowd.com


Re: how to properly secure non-ssl logins (php + ajax)

2009-02-20 Thread Joseph Ashwood
- Original Message - 
From: "Rene Veerman" 

Sent: Sunday, February 15, 2009 4:30 AM
Subject: how to properly secure non-ssl logins (php + ajax)


I'm going to edit this, since I assume most of the code is completely 
irrelevant


proposal:
database stores Hash(password | salt) on server
challenge = Hash(random bits), challenge specifically does NOT change every 
time

user_hash = Hash( Hash( password | salt) | challenge)

There are so many ways to attack this I'm not sure where to begin:
1) Man-in-the-middle - user <-> Jerk <-> server, Jerk can easily highjack 
the session

2) Fake server sends out known predictable challenges, user is now an oracle
3) hack the real server, retrieve Hash(password| salt) hacker can now log in 
to server FASTER than user
4) hash attacks, you mention specifically that MD5 is available as a hash 
for this, DONT EVER USE MD5


the list continues


Now how to (mostly) fix it:
g, p, q are DSA parameters of sufficient size
Hash is a secure Hash, SHA256 will work, but SHA512 will work faster
database stores g^Hash(password | salt) mod p, call it gUser
Challenge = time | random bits, make it 256 bits, using time reduces the 
number of random bits used

gChallenge = g^Challenge mod p
Signed-gChallenge = cryptographically signed gChallenge | time, this does 
not take a certificate, just a trusted known signature key


Client receives  Signed-gChallenge and salt
Client verifies signature including time on Signed-gChallenge and extracts 
gChallenge


Client computes Y = gChallenge^Hash(password | salt) mod p
Server computes Y = gUser^Challenge mod p

If Y=Y client knows the password. For proof of security, this is signed-half 
ephemeral Diffie-Hellman key agreement with reveal.


1) This does not fix the MITM attack, only an encrypted tunnel can do that, 
so use SSL
2) Fake server only repeat a challenge created by the real server because of 
the signature, but the public key of the signing key needs to be verifiable, 
this is where certificates come in
3) Retrieveing gUser from the database is exactly identical to retrieving a 
Diffie-Hellman public key, no risk, database can be public

4) ALWAYS REMEMBER TO NEVER USE MD5

Also with SSL you don't need to have a paid for certificate, have a look at 
https://financialcryptography.com/ for an example.
   Joe 


-
The Cryptography Mailing List
Unsubscribe by sending "unsubscribe cryptography" to majord...@metzdowd.com


Re: how to properly secure non-ssl logins (php + ajax)

2009-02-20 Thread Peter Gutmann
Rene Veerman  writes:

>Recently, on both the jQuery(.com) and PHP mailinglists, a question has
>arisen on how to properly secure a login form for a non-ssl web-application.
>But the replies have been "get ssl".. :(
>
>I disagree, and think that with a proper layout of authentication
>architecture, one can really secure a login system without having the
>administrative overhead of installing SSL everywhere, and the monetary cost
>for a SSL certificate for each domain.
>
>[...]
>
>I'm halfway (or more?) there, i think. For my own CMS, i have taken the
>following approach, which i'd like to hear your improvements on:

Go out and get a copy of "Network Security" by Kaufman, Perlman and Speciner,
this has an entire chapter that discusses this issue, including the pros and
cons of different approaches and all the ways you can get it wrong (oh, and
it's written for a non-security-geek audience).   I think any discussion here
will end up being mostly a rehash of bits of the chapter, their version goes
into much more detail and has diagrams to boot.

Peter.

-
The Cryptography Mailing List
Unsubscribe by sending "unsubscribe cryptography" to majord...@metzdowd.com


Re: how to properly secure non-ssl logins (php + ajax)

2009-02-20 Thread Jeffrey I. Schiller
I think you are close, but are probably doing way too much work.

First let's define a function HMAC_MD. HMAC is defined in RFC2104
and represents the current best current practice for using a hash to
"sign" a data value. It takes:

  result = hmac_md(key, value)

You can use hmac with MD5, SHA1, SHA256... whatever. You will likely
find libraries that already implement this in various languages.

Below "SHA" means SHA1, SHA256, your choice.

We'll assume each user has a password which is stored on the
server. For a bit of extra security I would have the server store it
as a SHA hash of the actual password.)


For authentication you do a challenge response.

   Server Client
nonce   >
<===username, hmac_md(sha(password), nonce)

The trick is to ensure that the nonce is not re-used. There are
several ways to do this. One way is to store it in a table:

  crate table nonces (
   nonce varchar(128),   # Probably enough
   ts  timestamp,
   used Boolean )

When the server gets the reply it looks up the user's "sha(password)"
which is stored in the user account table. It then verifies that the
nonce value is in the nonces table and that used is False. It then
verifies that the timestamp is "fresh" (you can decide this). Upon
use, the nonces table is updated to set used to True. A second login
attempt would require a separate nonce. Once a nonce is no longer
"fresh" it can be purged from the nonces table (so you don't have to
store these forever). Obviously the server computes
hmac_md(sha(password), nonce) and verifies it is the value received
from the client.

There are a copy of gotchas here. The biggest is how you initially
setup the shared secret (aka the password). Without public key
operations there is no good way to create accounts (unless this is
done administratively, effectively "off line"). SSL of course can
solve this (but you don't want to use SSL). You can also attempt to
implement RSA in javascript and PHP (well, I'm sure routines exist for
PHP). You can then download a public key in your javascript code for
account registration. The user's browser can then compute
sha(password) and send it encrypted in the public key (or encrypted in
a data encrypting key which is encrypted in a public key).

I don't know how amenable javascript is to doing RSA. Years ago (when
computers were much slower) I wrote a Java Applet that did RSA in the
applet for account registration at MIT. It wasn't very fast, but it
was good enough for a one-time registration applet. Heh heh, we still
use it today!

Now of course I really cannot end this message without throwing in the
obvious caution that without SSL your authentication is pretty
weak. Even though you have not exposed the user's password, once
logged in PHP uses a session cookie. This cookie, although of limited
lifetime, is now available to the eavesdropper to steak and abuse. I'm
not even sure that PHP ensures that a cookie is coming from the same
IP address it was issued to (and in fact you cannot usually implement
such a restriction because some environments [aka large NATs and other
crud] can result in a legitimate user's traffic coming from different
IP addresses even within the same web session!).

And of course all of your data is also exposed, both for viewing and
for modification in flight.

Last I checked, SSL certificates could be had for the $20/year range,
so I don't see how that is cost prohibitive!

Modern hardware also does SSL pretty darn fast. You really have to
have a very high traffic site before it becomes a problem. There
actually aren't that many high traffic sites out there. Most
organizations may think their sites are high traffic, but they rarely
are.

-Jeff

- "Rene Veerman"  wrote:

> Hi.
>
> Recently, on both the jQuery(.com) and PHP mailinglists, a question
> has arisen on how to properly secure a login form for a non-ssl
> web-application.  But the replies have been "get ssl".. :(
>
> I disagree, and think that with a proper layout of authentication
> architecture, one can really secure a login system without having the
> administrative overhead of installing SSL everywhere, and the monetary
> cost for a SSL certificate for each domain.

--

Jeffrey I. Schiller
MIT Network Manager
Information Services and Technology
Massachusetts Institute of Technology
77 Massachusetts Avenue  Room W92-190
Cambridge, MA 02139-4307
617.253.0161 - Voice
j...@mit.edu


-
The Cryptography Mailing List
Unsubscribe by sending "unsubscribe cryptography" to majord...@metzdowd.com


how to properly secure non-ssl logins (php + ajax)

2009-02-16 Thread Rene Veerman

Hi.

Recently, on both the jQuery(.com) and PHP mailinglists, a question has 
arisen on how to properly secure a login form for a non-ssl web-application.

But the replies have been "get ssl".. :(

I disagree, and think that with a proper layout of authentication 
architecture, one can really secure a login system without having the 
administrative overhead of installing SSL everywhere, and the monetary 
cost for a SSL certificate for each domain.


I wish to code such a solution into a really-free library (so probably 
LGPL or GPL + MIT) over the next 2 to 5 months.
This library would be a complete SQL, PHP & javascript package (jQuery 
"plugged in"), targetted for the novice programmer.


I'm halfway (or more?) there, i think.
For my own CMS, i have taken the following approach, which i'd like to 
hear your improvements on:


(For onewayHash() i have MD5 and SHA256 implementations in both JS and 
PHP..)


 SQL:

create table users (
 user_id   integer,
 user_login_name  varchar(250),
 user_login_hash  varchar(250),
 user_password_hash   varchar(250),
other fields
primary key (user_id)
);

create table preferences (
 pref_system_hash   varchar(250)

);

 PHP (pseudo-code) , on system installation:
   preferences.pref_system_hash = onewayHash ( randomStringLength(100) );

 PHP , on user-create:

  users[user_id].user_login_hash = onewayHash(user_login_name + 
preferences.pref_system_hash);
  users[user_id].user_password_hash = onewayHash 
("someGooodPasswordNot" + preferences.pref_system_hash);


 PHP, on request of a login form:

  challenge = makeNewChallenge ();
   //checks since when [browser IP] has last received a new 
challenge, if < threshold : make a new challenge. else return old challenge.
  //a challenge is a random string (+ special chars) pushed through 
the onewayHash function.


  html = '
  
 value="preferences.pref_system_hash">

 
 
 
 
 
  
   ';
   sendHTMLtoBrowser (html);

 Javascript: on page with login form:

   jQuery('#loginForm').submit (function () {
 var sh = jQuery('#sh')[0]; //same for ch, plain_user, 
plain_pass, all the inputs in the html form.

 

 user_hash = onewayHash ( onewayHash ( plain_user.value + 
sh.value ) + challenge );

 //same for pass_hash basically

 plain_user.value = ''; //clear out the plain text fields so 
they dont get transmitted (same for plain_pass ofcourse)


 jQuery.ajax ( /* submit login form through POST, handle 
results */ )

   }


 PHP, on receiving the login form data:

  // walk through all the records in users table, for each, calculate:
 user_hash = onewayHash ( users[user_id].user_login_hash + 
challenge );
 pass_hash = onewayHash ( users[user_id].user_password_hash + 
challenge );


  // if they match what was sent, then it's the user we're looking 
for with the right password, so their $_SESSION['authenticated_user'] = 
updated.





If you have a completely alternative way of securing a non-ssl login 
form, i'd like to hear about it too.



-
The Cryptography Mailing List
Unsubscribe by sending "unsubscribe cryptography" to majord...@metzdowd.com