Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authentication improvement: Prevent cleartext passwords being sent to server #1190

Closed
evilaliv3 opened this issue Mar 10, 2015 · 20 comments
Closed

Comments

@evilaliv3
Copy link
Member

It would be interesting (and important) to improve the authentication mechanism implemented by globaleaks by preventing cleartext password being sent to the server.

_n.b._ this idea does not replace password hashing+salting on serverside, but simply want to avoid that the server knows the cleartext password (possible reused by the user so making the server itself not in possibility to stole reused password)

Current user password (e.g. "helloworld") reach the server in clear-text, the server stores the a hash salted with a secret salt. this way the second time that it get a password, it verify it be re-salting with the stored salt. this protect by rainbow tables attacks but makes the server in possibility to reuse "helloworld" on other accounts of the user.

The idea is that the server should provide also a public salt so that the client would never send the password in a clear-text format.
Authentication will act as following:

  • The clients read the /node resource and get the global salt (this can be global and different per node)
  • The client hash the original_password(helloworld) with this public salt.
  • The server continue the authentication with a unix like fashion considering as password not the hello world but hash(helloworld, public_salt).

The reason for a public salt in addition to a private salt is to not disclose the user salt making possible to speed up rainbow tables attacks.

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@evilaliv3
Copy link
Member Author

the approach followed to address this ticket could be probably the same of #1176

siimply the password used by the user will be password = scrypt(possibly_reused_password)

@fpietrosanti
Copy link
Contributor

Hi all,

that's the suggested scrypt implementation to be used within GlobaLeaks from the Cryptography mailing list.

-------- Forwarded Message --------
Subject: Re: [cryptography] Javascript Password Hashing: Scrypt with WebCrypto API?
Date: Wed, 11 Mar 2015 18:01:21 +0300
From: Solar Designer [email protected]
To: Alfonso De Gregorio [email protected]
CC: Fabio Pietrosanti (naif) - lists [email protected], Crypto discussion list [email protected]

On Wed, Mar 11, 2015 at 02:20:42PM +0000, Alfonso De Gregorio wrote:

Until more browsers start supporting PBKDF2 with HMAC-SHA-256, you
might be better of reverting to a JavaScript library, to be plugged in
your scrypt implementation. I never took the chance to look at it, but
I heard that asmcrypto.js provides the fastest PBKDF2-HMAC-SHA-256
implementation in town [2].

The uses of PBKDF2-HMAC-SHA-256 in scrypt are not performance-critical.
When scrypt is invoked with sane settings, most of the processing time
is spent in scrypt's SMix, not in PBKDF2.

This might be the most suitable implementation of scrypt in JavaScript:

https://github.com/dchest/scrypt-async-js

Its performance test:

http://dchest.github.io/scrypt-async-js/demo.html

Alexander

@origliante
Copy link

this is implemented in the end2end with a pass of scrypt before the receiver's password change and before the login submit. @evilaliv3 I add this to the e2e todo

@hellais
Copy link
Contributor

hellais commented Apr 16, 2015

@origliante is the authentication scheme specified somewhere? I would be happy to take a look at it. I believe that the idea of having a challenge response mechanism based on public key based signing could be a valid option.

@evilaliv3
Copy link
Member Author

it's still not specified; the specification should be studied as addition to the application security document.

@evilaliv3
Copy link
Member Author

anyway @hellais what I want to address with this ticket is simply to have a mechanism that not make use in possibility to get the cleartext password choosen by the receiver;

i want simply to avoid that a node whould to be in possibility to reuse the password of the user to access other user services and this has been solved by our specification of having the client do:

password_sent_to_server = scrypt(node_salt, user_password)

this, that is part of our end2end solution and has already been implemented in the end-to-end branch, solves the issue I opened.

@hellais
Copy link
Contributor

hellais commented Apr 16, 2015

Is this what you mean:

https://github.com/globaleaks/GlobaLeaks/blob/feature/end2end/client/app/scripts/e2e.js#L5

?

I believe some precautions still need to be taken when using the node salt (like it being of poor entropy or even being null).

Implementing what I propose above would be a matter of doing what is described in section "7. Public Key Authentication Method: "publickey" of RFC4252

@evilaliv3
Copy link
Member Author

wait, i'm not saying your proposal is not right, but its not relevant to this ticket that i consider closed by what we agreed during the hackaton that is what i written in the last comment.

fabio also suggested a different protocol that if i not remember wrong is more standard in relation to a web application than ssh that also if standard is more specific.

@evilaliv3 evilaliv3 modified the milestones: 2016 March, Wishlist Mar 14, 2016
@NSkelsey
Copy link
Contributor

@hellais you are suggesting having the user store a key on their machine and then load it into the browser for authentication correct? From my understanding it is desirable to keep the receiver from remembering anything other than a passphrase. HOWEVER, if the receiver is already using a PGP key why not make it easier for them to authenticate...

@evilaliv3 in lieu of public key based auth, we could use the Secure Remote Password (SRP) protocol for handling passphrase based authentication – or at least the passphrase side of authentication.

SRP is an interactive protocol that only relies on a client passphrase. Conceptually it is very similar to passing a hashed and salted token to the server, but a passive or active observer can take no information away from observing a successful login (something a static salt does not protect against.) RFC 2945 provides more detail:

Abstract

   This document describes a cryptographically strong network
   authentication mechanism known as the Secure Remote Password (SRP)
   protocol.  This mechanism is suitable for negotiating secure
   connections using a user-supplied password, while eliminating the
   security problems traditionally associated with reusable passwords.
   This system also performs a secure key exchange in the process of
   authentication, allowing security layers (privacy and/or integrity
   protection) to be enabled during the session.  Trusted key servers
   and certificate infrastructures are not required, and clients are not
   required to store or manage any long-term keys.  SRP offers both
   security and deployment advantages over existing challenge-response
   techniques, making it an ideal drop-in replacement where secure
   password authentication is needed.

Improvements to the protocol are described in RFC 5054. I have some personal experience with this protocol, but I do not believe that the protocol makes it easy to pick security parameters. The specification provides a few, but I have no idea what sort of properties the primes provide.

There are many implementations of SRP in python and JS. In my opinion, it is a moot point to focus on javascript based authentication until the loaded scripts can be trusted, which seems like a long way away...

@evilaliv3
Copy link
Member Author

@NSkelsey: correct if i'm wrong but i think that given the fact that we have Tor or TLS we would have no benefit of SRP as both the channel would anyhow provide the same properties.

The main idea here was simply not make the cleartext password land on the server but simply a scrypt(password, node_salt) this way even if the user will reuse hello world on all the servers an attacker would have to build rainbowtables to got the initial password. Obviously this is not intended to protect the authentication on the node as the password for the server will be password_for_the_server scrypt(password_for_the_user, node_salt), but at least if the user has reused the password_for_the_user on more nodes the node could not impersonificate the user on the other servers. got the point?

@fpietrosanti what do you think?

@fpietrosanti
Copy link
Contributor

@evilaliv3 Yes, with the regards to authentication i agree too that SRP is the ideal way to go for authentication, as per analysis already done in past, with some small improvement to the the standard RFC where i triggered peer analysis on cryptography mailing list (see bitwiseshiftleft/sjcl#214 && symeapp/srp-client#8 && mozilla/node-srp#28), but that has never been done due to other complexity with client-side pgp.

In the perfect/ideal world we would use SRP6a with scrypt() improvement relying on an underlying additional independent/unauthenticated TLS exchange as per digitalbazaar/forge#81 and sqs/tlslite#4 but that would require a lot of additional crypto work.

I may suggest to integrate the OpenPGP.js library in our workflow, without touching current cleartext authentication (or the simple-to-be-implemented proposal you've done), this will probably break everything and cause months of hard-work only to make it working in a reasonably way, then as a last topic we'll handle authentication improvement?

@NSkelsey
Copy link
Contributor

@evilaliv3 you are right that TLS protects from eavesdroppers and everything on top of it is just extra. If there is an active attacker in the channel then the user is doomed anyway.

However, if a GL node relies on a tor2web relay then with just scrypt(password, salt) the tor2web relay learns the login token (and can start brute forcing the password). With SRP, an attacker has to get to the GL node's database before he can start cracking. So there is a slight advantage there.

But in the medium term run with scrypt(password, node_salt), it is much simpler.

@fpietrosanti I think supporting a second factor for authentication is a better route for strong authentication. Many websites are starting to support FIDO's U2F protocol, which relies on hardware security tokens. It is unclear if Firefox (which would mean the Tor browser) will eventually support the protocol, but it is still a possibility.

I think for the committed groups that use GL this is a safer option to use in addition to passwords (and while slightly off topic, worth bringing up). It also means you could give journalists something nice to put on their key chain!

@vodkina
Copy link
Contributor

vodkina commented Mar 21, 2016

estimate, please

@evilaliv3
Copy link
Member Author

@fpietrosanti / @NSkelsey: with @vecna we agreed that to do this and given the fact that the scrypt process require a salt that we will implement the protocol that i suggestsed.

the authentication will work as follow:

  • the client will provide a username
  • the system will provide back the corrisponding salt or a random salt to not dislose user existance or not.
  • the client will use the salt for derivate the password and perform authentication.

for what relates to the whistleblower instead there will a per node salt as now exported in /node.

the salts so will stop to be secrets but we will benefit anyhow of:

  • requiring to the attacker to implement rainbow tables
  • not disclosing that different users are using the same password

i'm going to apply this changes along with the implementation of #1176; both are requirement to the implementation of the end2end encryption.

@NSkelsey
Copy link
Contributor

@evilaliv3 this seems reasonable. Definitely going in the right direction.

@evilaliv3
Copy link
Member Author

i've an important doubt in the migration;

  • as discussed with @vecna we would like to have two different functions for password hashing (used for auth) and password derivation (used for protecting the pgp key).
  • as discussed with @fpietrosanti we would like to have one and no more than one scrypt process done by the client to make things anyhow feasible.

i would suggest to have:

  • sha512 for the password hashing
  • scrypt for the password derivation; parameters to be discussed.

the part problematic will be the migration as it would require to handle the special condition of having to do the fallback on the legacy authenticator for the first login so that a lot of the old code should stay anyhow in plae on an handler /authentication-legacy were to switch from the current server hash (that is a script with default argument used in the python signature (scrypt.hash(password, salt, N=1 << 14, r=8, p=1, buflen=64)) but anyhow we will have to handle the first login so we could implement the following basic logic:

try new login; if the answered salt is empty proceed with legacy login on /authentication-legacy

this will leak which are the user that are still not using the old authenticatiion but is the only way to guarantee the migratiion.

@evilaliv3 evilaliv3 modified the milestones: 2016 April, 2016 March Apr 2, 2016
@evilaliv3 evilaliv3 modified the milestones: 2016 May, 2016 April May 2, 2016
@evilaliv3 evilaliv3 modified the milestones: 2016 June, 2016 May Jun 2, 2016
@evilaliv3
Copy link
Member Author

@NSkelsey: this could be a nice to have to already backport in devel.

@NSkelsey
Copy link
Contributor

NSkelsey commented Jun 2, 2016

No backports for you!

@evilaliv3
Copy link
Member Author

This is implemented and finalized in the browsercrypto branch and it's documentation is part of writing the browsercrypto specs; then will follow updating the application security document.

@NSkelsey
Copy link
Contributor

NSkelsey commented May 8, 2017

Notes on SRP from discussion today

SRP 6a + storage of password’s related material + https://lists.randombit.net/pipermail/cryptography/2015-March/007120.html

Support scrypt into SRP6a in order to avoid weak password storage symeapp/srp-client#8

Authentication improvement: Prevent cleartext passwords being sent to server #1190 (comment)

Thinbus Javascript Secure Remote Password (SRP) https://bitbucket.org/simon_massey/thinbus-srp-js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

6 participants