5

Given that a communication over HTTP

  • uses SSL encryption
  • uses public key pinning to prevent MiTM attacks

is security in any way elevated by using Salted Challenge Response Authentication Mechanism (SCRAM) over basic access authentication and subsequently a token for every request?

qnoid
  • 253
  • 1
  • 5

3 Answers3

4

tl;dr: I wouldn't generally recommend it, but it may be useful in specific circumstances

Advantages of SCRAM

  • The password is never sent to the server. The only things sent on the wire are:
    • The nonce
    • The salt
    • The iteration count
    • HMAC(PBKDF2(password), "Client Key") XOR HMAC(H(HMAC(PBKDF2(password), "Client Key")), AuthMessage) (seriously, I'm not making this up!)
    • HMAC(HMAC(PBKDF2(password), "Server Key"), AuthMessage)
  • The server never knows the password, and thus can't impersonate the user on other servers (as long as the salt on those servers is distinct from this server's salt)

Disadvantages of SCRAM

  • Requires the use of PBKDF2. While PBKDF2 is significantly better than a fast hash, bcrypt is better (and nowadays you should consider Argon2 as well).
  • Requires that all of the computational complexity be handled by the client

The first point is unfortunate, but the second point is the real killer. With smartphones and tablets everywhere now you simply can't assume that the client will be able to quickly compute PBKDF2 with enough iterations to be safe.

When would SCRAM be useful?

The use I see for SCRAM is where the client is trusted but the server is not. This is never true for a web application (as the "client" is the JavaScript sent by...the server), and is only sometimes true for local applications. The best examples I can think of are the ones Wikipedia gives: SMTP, IMAP, and XMPP, where you trust your email or chat client but are authenticating to a potentially malicious third party server.

If the client forces a high iteration count and unique salt it may mitigate the risk of DNS hijacking combined with a rogue CA, but you've already done that with certificate pinning. The only thing left to defend against is your server being malicious, which may be useful in some cases, but only if the gains outweigh the disadvantages of SCRAM.

SCRAM could useful to keep the server from obtaining the password if you know that a strong password will be used, but that the password will also be re-used elsewhere (if it's not reused why would you care if the server might know it?). Unfortunately this can't really be enforced, and the ideal would be to use a unique password anyway.


How does SCRAM work?

In SCRAM, the server stores:

  • The salt
  • The iteration count
  • ServerKey = HMAC(PBKDF2(password), "Server Key") (where "Server Key" is a known constant HMAC key)*
  • StoredKey = H(HMAC(PBKDF2(password), "Client Key")) (ditto for "Client Key")

To authenticate:

  1. The client sends the username and a random nonce
  2. The server appends its own random nonce to the client's, and replies with the nonce, salt, and iteration count for the user
  3. The client computes the following:
    1. ClientKey = HMAC(PBKDF2(password), "Client Key")
    2. StoredKey = H(ClientKey)
    3. ClientSignature = HMAC(StoredKey, AuthMessage) (where AuthMessage is the concatenation of all previously exchanged messages and the nonce, delimited by commas)
    4. ClientProof = ClientKey XOR ClientSignature
  4. The client sends the nonce and ClientProof to the server
  5. The server computes the following:
    1. ClientSignature = HMAC(StoredKey, AuthMessage)
    2. ClientKey = ClientProof XOR ClientSignature
    3. ServerSignature = HMAC(ServerKey, AuthMessage)
  6. The server verifies H(ClientKey) == StoredKey, proving that the client knows the password (or at least ClientKey)
  7. The server replies with ServerSignature
  8. The client computes ServerSignature and compares it to the value returned by the server, verifying that the server knows the ServerKey

This is rather simplified, as it excludes some things like hash selection, encoding, message format, and channel binding, but it should give a good idea of how it works.

* All uses of PBKDF2 obviously include the salt and iteration count as well, SCRAM sets dkLen to the output length of the selected hash

AndrolGenhald
  • 15,436
  • 5
  • 45
  • 50
  • "The server never knows the password, and thus can't impersonate the user on other servers (as long as the salt on those servers is distinct from this server's salt)" that is indeed a benefit of SCRAM but it does not elevate security between the client and a server, correct? – qnoid Jul 04 '18 at 07:08
  • "The use I see for SCRAM is where the client is trusted but the server is not." Can you elaborate further please? Are you referring to the "server signature" that SCRAM uses? If so, isn't that weak when it comes to HTTP because of a MiMT attack? Isn't public key pinning the secure option? Re "your server being malicious", AFAICS the scenario here is that as an attacker you want to compromise a previously authenticated client, right? "useful to keep the server from obtaining the password" which is also about server security. It does not elevate in any way the client - server one, correct? – qnoid Jul 04 '18 at 07:23
  • 1
    @qnoid Correct for both points, I added SMTP, IMAP and XMPP as examples of where you might trust the client but not the server. If the same developer is making both the client and the server that scenario wouldn't usually apply (Signal is an exception that comes to mind, because they want to be as paranoid as they can). The only real advantage here is that you're not sending your password to an untrusted server, which only really matters if you re-use that password. – AndrolGenhald Jul 04 '18 at 11:40
  • For client-server security key pinning is just about the best thing you can do, just make sure you don't allow weak ciphers (and of course the server still shouldn't trust the client fully, as it could be reverse engineered). Also, SCRAM can absolutely be used with HTTPS, and that would still be preferred, it's just not quite as disastrous if used with HTTP. – AndrolGenhald Jul 04 '18 at 11:43
  • Some benefits will be implementation specific, ex: Apache Kafka requires a rolling broker restart if you use PLAINTEXT user/password (which is stored on each broker), but *does not* require a restart if you use SCRAM (because auth info will be stored in Zookeeper). – xref Aug 13 '19 at 21:05
2

A common security flaw is logging plaintext passwords by mistake:

Even if you have transport security, it has advantages to not have the plaintext password on your server. Transport security protects against attackers. If you want to protect yourself against your own mistakes, you need client side hashing.

Sjoerd
  • 28,707
  • 12
  • 74
  • 102
1

The RFC points the following advantages:

o The authentication information stored in the authentication database is not sufficient by itself to impersonate the client. The information is salted to prevent a pre-stored dictionary attack if the database is stolen.

o The server does not gain the ability to impersonate the client to other servers (with an exception for server-authorized proxies).

o The mechanism permits the use of a server-authorized proxy without requiring that proxy to have super-user rights with the back-end server.

o Mutual authentication is supported, but only the client is named (i.e., the server has no name).

Your question considers only the connection security, while SCRAM takes into account the security of the client credentials too. Its most distinct advantage is that it prevents the server operators from getting user credentials, as they are transmitted in a salted and hashed format, while on a simple TLS connection it travels on clear text.

ThoriumBR
  • 50,648
  • 13
  • 127
  • 142
  • By "impersonate the client"; does this mean that the server (or an unauthorised 3rd party in case of a theft) cannot identify as the client since it does not know the password? Not sure what "The information is salted to prevent a pre-stored dictionary attack if the database is stolen." means. AFAICS, the server database only holds the stored and server key which alone, cannot be used to perform a dictionary attack on the password. The second and third points sounds to me more related to privacy than security. Last point I infer is re server signature. Effectively what public key pinning does? – qnoid Jul 04 '18 at 07:06
  • Public key pining puts a specific key on the client, and it will only accept that key. If someone creates another certificate, even a valid one, the client will abort the connection. – ThoriumBR Jul 04 '18 at 11:43