Introduction to authentication:

Confidentiality and authentication are necessary for security assurance over a telecommunication channel. “Confidentiality” assures that only the right users have access to the communication stream and “authentication” guarantees that the users at each end of the communication channel are who they say they are. The Salted Challenge Response Authentication Mechanism (SCRAM) is a standardized authentication technique. This article discusses this mechanism briefly using the codes attached.

Current Setting in PostgreSQL:

PostgreSQL has two principal methods to authenticate the users: A. Password-based:

  • password (plaintext)
  • md5
  • RADIUS / LDAP / PAM

B. Others:

  • SSL certificate
  • Kerberos

Limitations/Drawback with the current authentication methods:

  • RADIUS, LDAP, PAM, and BSD authentication methods uses plain password authentication. As known, this method is obviously weak and passwords can be sniffed easily.

  • In MD5 authentication, there is duplication of the 4-byte salts. Secondly, one does not need the original password to log in. The hash value stored in pg_auth.rolpassword is enough to get connected. Also, renaming a user invalidates the password because the hash includes the username.

What happens . .

The primary method to authenticate oneself to an entity is to show that one holds some secret passcode that can be presented when required. Typically, one presents a user name and/or a password that authenticates him/her to the challenging entity. Sometimes the authentication process has to be mutual i.e. A authenticates herself to B and B authenticates himself to A.

SCRAM belongs to a class of protocols that provide the mutual authentication facility. In SCRAM, like many other secure authentication mechanisms, the password or secret information is never transmitted during the execution of the protocol. Instead, the secret information along with a cryptographically secure random value is used to compute another value at each end of the communication channel. It is this computed value that is transmitted. On receipt of the transmitted value, the communicating parties compare their computed value to the received value. If these values match then the authentication process is successful, otherwise it fails.

The SCRAM Mechanism

The SCRAM protocol assumes that one end of the communication channel is the client and the other end is a server.

he execution of SCRAM involves the transmission and processing of four messages. As can be seen in the image above, the client begins the process by sending the Client First Message and in response to the reception of a validly formatted first message from the client, the server sends the Server First Message to the client. The client processes this message and if everything is okay, it transmits the Client Final Message. The server, as expected, processes this message. At the end of this task, the server should know if the client is successfully authenticated or not. If it is, the server sends the Server Final Message, otherwise it sends an authentication failure message to the client or sometimes may not. With the reception of the Server Final Message, the client is also able to authenticate the server.

There are four cryptographic values that are central to the SCRAM protocol. These values are;

  • Client nonce: Using a cryptographic random generator the client generates a random value. This value along with the client’s user name is contained in the Client First Message. Ideally, the client nonce value must be different for each authentication session.
  • Server nonce: This is similar to the client nonce and it is contained in the Server First Message. This value must be different for each authentication session.
  • Salt: The Salt is a cryptographically secure random number generated by the server. This Salt value and the password are fed into a one-way cryptographic function that generates another value. The Salt is contained in the Server First Message and it hides the password.
  • Iteration Count: This is a numerical value generated by the server that indicates how many times the cryptographic function mentioned above should be applied to the Salt and the password to generate its output. This Iteration Count value is transmitted in the Server First Message.

SCRAM in PostgreSQL

in order to use this feature, PostgreSQL 10 has extended the configuration parameter “password_encryption” with the value ‘scram-sha-256’, to allow the definition of passwords hashed with SCRAM:

Let us first see what happens with the current md5 authentication method. We shall create a user named ‘Jack’, get the password value from pg_authid, then drop and re-create the user with the same password.

postgres=# show password_encryption;
 password_encryption 
---------------------
 md5

postgres=# create role jack with password 'jack' login;
CREATE ROLE
postgres=# select rolname, rolpassword from pg_authid;
      rolname      |             rolpassword             
-------------------+-------------------------------------
 postgres          | md53175bce1d3201d16594cebf9d7eb3f9d
 jack              | md54b70c5a3ebfb5f8706b297db179cbaf6

Let us drop the role and re-create it again with the same password.

postgres=# drop role jack;
DROP ROLE
postgres=# create role jack with password 'jack' login;
CREATE ROLE
postgres=# select rolname, rolpassword from pg_authid;
      rolname      |             rolpassword                                                          
-------------------+-------------------------------------------------------------
 postgres          | md53175bce1d3201d16594cebf9d7eb3f9d
 jack              | md54b70c5a3ebfb5f8706b297db179cbaf6

We see that dropping a user and re-creating the user, creates the same md5 hash password.

Let us now try the same with SCRAM by creating a user, dropping, and then re-creating again. To do this, the password_encryption should be set to scram.

postgres=# SET password_encryption = 'scram-sha-256';
SET
postgres=# create role john with password 'john' login;
CREATE ROLE

postgres=# select rolname, rolpassword from pg_authid;
      rolname      |              rolpassword                                                          
-------------------+---------------------------------------------------------------
 postgres          | md53175bce1d3201d16594cebf9d7eb3f9d
 jack              | md54b70c5a3ebfb5f8706b297db179cbaf6
 john              | SCRAM-SHA-256$4096:cPOd7KrzlptaiRZY$cbM7EM1kDhziGNWKkNYUG2jap
                     Bho9hnVdeA1hEJ5PnQ=:lP69GgVhToQzqWIEgLd60k6K2Z02rOZPEJoJ2nb86Ck=

##Dropping and re-creating the user 'john'

postgres=# drop role john;
DROP ROLE
postgres=# create role john with password 'john' login;
CREATE ROLE
postgres=# select rolname, rolpassword from pg_authid;
      rolname      |               rolpassword                                                          
-------------------+---------------------------------------------------------------
 jack              | md54b70c5a3ebfb5f8706b297db179cbaf6
 john              | SCRAM-SHA-256$4096:NS8YtwCfCIKHA7tW$aFlB/tvKoMvJq3l4phGcKTQbU
                     H2opCasYxGnLFetsT0=:hl18+F6fBDwvFM2XNESrASh6h4Uzzp+ByG99SIln2wI=

So user with the same name and the same password will have different hash value.

Inorder to authenticate a user with SCRAM method, pg_hba.conf need to be updated. Reload the PostgreSQL server once done.

# TYPE  DATABASE   USER       ADDRESS           METHOD
# "local" is for Unix domain socket connections only
local   all        all                          trust
# Use plaintext authentication from localhost
host    all        all        127.0.0.1         
plain
# Allow md5 authentication from example.com, with SSL
hostssl all        all        .example.com      
md5
# Require SCRAM for everyone else
host    all        all        0.0.0.0/0         scram-sha-256

Advantages of SCRAM:

  1. SCRAM authentication method is relatively simple to implement.
  2. It is more resistant to dictionary attacks. The computation to guess password is much more resource intensive.
  3. Iteration count can be configured.
  4. Longer nonces defeat replay attacks.
  5. The verifiers stored in pg_authid.rolpassword do not allow impersonating the user.
  6. Storing hashed passwords on the server and sending them out plain during authorization greatly mitigates the disaster of password table leakage, but of course this setup is vulnerable to eavesdropping. Challenge-response protocol used in PG prevents eavesdropping but unfortunately at the price of high risk of leaking server passwords and hashing them doesn’t help much: if attacker knows hashed password he has enough information to succeed with challenge-response authentication.
  7. SCRAM on the other hand cleverly combines the advantages of the above approaches so that neither password db leakage nor eavesdropping pose much threat.

Caveat:

SCRAM does not provide one-stop solution. The SCRAM specification strongly advises that the protocol should be exchanged over an encrypted channel. The idea is to prevent an eavesdropper from extracting the contents of these messages in transit and then using the values contained within to mount an off-line dictionary attack to extract the password.