0

I'm currently developing an Android Application that communicates with a server and needs the user to login.

The connection is secured with SSL and certificate pinning.

For user authentication I'm currently using challenge-response.

The server stores a PBKDF2 hash of the password and the salt used in the PBKDF2 (called PBKDF2(password,salt) ). Parameters for PBKDF2 are: 10k iterations, SHA256, 32 byte output length.

The flow works as follows:

The Client transmits PBKDF2(Username,Salt) and the Salt

The Server looks up the username and sends back the password-salt and a 32 byte challenge.

The client returns PBKDF2(challenge,PBKDF2(password,salt)).

The server verifies the response and returns a session-token.

So neither the username nor the password are transmitted over the channel.

SSL in and of itself should be pretty secure, and adding certificate pinning should make it resistant to MITM.

Am I overlooking any flaws?

Or is the whole thing overkill given the fact that the connection is SSL encypted?

  • What requirements make you move to this approach? What are you trying to protect against? – Limit Nov 30 '20 at 05:18
  • @Limit The main goal is to avoid sending any form of sensitive information over the wire. Making the assumtion, that the connection is unecnrypted, I want to protect against: Replay attacks, Password stealing, Username stealing (whether or the username is sensitive information, is debatable, but if I can protect it, I would like to do so) – Thunderbolt Nov 30 '20 at 09:10
  • SSL does solve for reply attacks, the content is encrypted as well. Given that you are pinning the SSL cert, you should be better protected against the MITM attacks as well. – Limit Nov 30 '20 at 12:32
  • Why the assumption of unencrypted connection when you are using SSL? – Limit Nov 30 '20 at 12:33
  • @Limit More or less proof of concept, whether I can implement something that does not rely on the channel encryption. Might be nonsense since I'm using SSL and could just send the PW in plaintext, but for me it's a nice challenge. but i'll probably just dail it back and just get the PW Salt from the server and send the hash... – Thunderbolt Nov 30 '20 at 20:18

1 Answers1

1

The Client transmits PBKDF2(Username,Salt) and the Salt
The Server looks up the username and sends back the password-salt and a 32 byte challenge.

The server cannot extract the username directly from the PBKDF2(Username,Salt) since PBKDF2 is a one-way hash and not encryption. The server would need instead to compute the PBKDF2 with the specific salt for all users in the database whenever a user logs in until it has found the matching user. Given that PBKDF2 is explicitly designed to be slow this is a powerful vector for a denial of service.

Apart from that - it is unclear why the username need to be protected like this in the first place.

The client returns PBKDF2(challenge,PBKDF2(password,salt)).

Since the server does not transmit the salt which has to be used by the client, the salt used in this client response and the salt used by the server when storing the password are not the same. I.e. the client is using in its response PBKDF2(password,client_salt) while the server has stored PBKDF2(password,server_salt) with client_salt and server_salt being different. To compare the response from the client the server would have to compute it too, but it would need the original password for this. But again, PBKDF2 is a one-way hash, so it is impossible for the server to extract the original password from the server-side stored hash.

This means that the server cannot check the validity of the clients response, which means the whole authentication process does not work.

... and adding certificate pinning should make it resistant to MITM.

Certificate pinning is no magic bullet against MITM.
It only protects against a specific attack: that the attacker is able to get a certificate created by a CA which is is trusted by the client and where the CA matches the domain name. It does not protect against the attacker having access to the original certificate for example by compromising the server. It also does not protect against attacks against client or server directly, i.e. get access to the information before encryption or after decryption.

Or is the whole thing overkill given the fact that the connection is SSL encypted?

First, it does not even work as shown. It only introduces an additional DoS vector. Since it is not clear what kind of attack the added complexity should even address it likely does not add any relevant value to simply using HTTPS. And if you want to have a working challenge-response method have a look at Digest Access Authentication instead.

Steffen Ullrich
  • 184,332
  • 29
  • 363
  • 424
  • > Since the server does not transmit the salt which has to be used by the client it does, see step 2 `The Server looks up the username and sends back the password-salt and a 32 byte challenge.` > The server cannot extract the username directly from the PBKDF2(Username,Salt) since PBKDF2 is a one-way hash and not encryption. I'm aware of the limitations and performance hits of this apporach. The first step might be to dail that back and move to a simple hash. – Thunderbolt Nov 30 '20 at 08:38