Authentification scram-sha-256
et migration depuis md5
¶
À propos
Auteur | Christophe Courtois |
---|
Objet¶
L’authentification par mot de passe avec chiffrage du mot de passe au format SCRAM-SHA-256 est disponible depuis PostgreSQL 10. Elle est celle par défaut depuis PostgreSQL 14, mais sa mise en place est conseillée pour les versions précédentes.
Cette nouvelle méthode d’authentification est bien plus sécurisée que l’ancienne méthode avec hachage MD5. Avec cette dernière, un même mot de passe pour un même nom d’utilisateur est haché et stocké de manière identique sur tous les serveurs PostgreSQL, alors qu’avec SCRAM-SHA-256 le hachage peut être différent même pour des mots de passe identiques.
La migration des mots de passe existants en md5
à scram-sha-256
n’est pas compliquée.
Elle n’est pas faite automatiquement lors d’une migration (ni par pg_upgrade
ni par pg_dump
) car il est impossible de déchiffrer les mots de passe pour les rechiffrer.
La cohabitation des deux systèmes est possible au cas où des clients encore incompatibles la rendraient nécessaire.
Configuration de postgresql.conf
¶
S’il vaut encore md5
, ce paramètre doit être modifié :
Il s’agit uniquement de la valeur par défaut, pour les mots de passé que l’on va entrer. Dans une session, on peut choisir une valeur différente. Les mots de passe existants ne sont pas affectés par ce changement.
Table pg_authid
¶
Cette table contient les hachages des mots de passe utilisateur (champ rolpassword
).
Le début du mot de passe indique le hachage, md5..
ou SCRAM-SHA-256$…
(voir exemples plus bas), qui peut différer selon les utilisateurs.
Configuration du fichier pg_hba.conf
¶
Il peut contenir des valeurs différentes selon les lignes :
# TYPE DATABASE USER ADDRESS METHOD
host all dalibo ::1/128 md5
host all postgres 192.168.1.5/32 scram-sha-256
Transition¶
À savoir : indiquer la méthode md5
dans pg_hba.conf
permet d’accepter des mots de passe chiffrés en MD5 comme en SCRAM-SHA-256. Par contre, indiquer la méthode scram-sha-256
impose que le mot de passe soit haché en SCRAM-SHA-256.
Cela autorise une migration progressive des utilisateurs, certains restant dans l’ancien hachage hérité d’une version précédente de PostgreSQL, les autres ayant mis à jour leur mot de passe.
Une fois tous les mots de passe migrés, remplacer md5
par scram-sha-256
garantit que l’ancienne méthode md5
peu sécurisé ne pourra plus être utilisé.
Exemple¶
Soit un utilisateur créé avec un mot de passe en md5
(défaut avant la v14). Son mot de passe est stocké sous forme d’un hachage md5
:
postgres=# SHOW password_encryption ;
password_encryption
---------------------
md5
postgres=# CREATE ROLE dalibo LOGIN PASSWORD 'aiWojo3roozahyah1uop' ;
CREATE ROLE
postgres=# SELECT * FROM pg_authid WHERE rolname = 'dalibo' \gx
-[ RECORD 1 ]--+------------------------------------
oid | 4209435
rolname | dalibo
...
rolpassword | md58de13651207b80138624353c9e6eda71
Sa connexion est autorisée par cette ligne dans le pg_hba.conf :
$ psql -h localhost -U dalibo -d postgres
Mot de passe pour l'utilisateur dalibo :
psql (13.2 (Ubuntu 13.2-1.pgdg20.04+1))
Connexion SSL (protocole : TLSv1.3, chiffrement : TLS_AES_256_GCM_SHA384, bits : 256, compression : désactivé)
Saisissez « help » pour l'aide.
postgres=>
Pour mettre à jour ce mot de passe en scram-sha-256
, il faut le re-rentrer après modification de password_encryption
(globalement ou dans la session) :
postgres=# SET password_encryption TO "scram-sha-256" ;
SET
postgres=# \password dalibo
Saisissez le nouveau mot de passe :
Saisissez-le à nouveau :
postgres=# SELECT * FROM pg_authid WHERE rolname = 'dalibo' \gx
-[ RECORD 1 ]--+--------------------------------------------------------------------------------------------------------------------------------------
oid | 4209435
rolname | dalibo
...
rolpassword | SCRAM-SHA-256$4096:4K6BIkV5+90l1aKfVQA17g==$FVGK4gxpLldtko08jGL7mZy5W3QacsUoxRknoiPe4UE=:a90+eT1Lh5bj9CHndrmHyblX0RxI+NdD86UaNSbrigs=
La connexion se fait alors tout aussi bien, sans modification de pg_hba.conf
.
Pour sécuriser la configuration et interdire le hachage md5
, il faut modifier pg_hba.conf
, et recharger la configuration :
Mais si on devait décider pour une raison ou une autre de revenir en hachage md5
, la connexion ne serait plus possible :
postgres=# SET password_encryption TO md5;
SET
postgres=# \password dalibo
Saisissez le nouveau mot de passe :
Saisissez-le à nouveau :
$ psql -h localhost -U dalibo -d postgres
Mot de passe pour l'utilisateur dalibo :
psql: erreur : FATAL: password authentication failed for user "dalibo"
FATAL: password authentication failed for user "dalibo"
Les traces contiennent alors cette erreur :
2021-05-07 17:20:20 CEST [4078090]: [3-1] user=dalibo,db=postgres,app=[unknown],client=::1
DETAIL: User "dalibo" does not have a valid SCRAM secret.
Connection matched pg_hba.conf line 99: "host all dalibo ::1/128 scram-sha-256"
Générer des mots de passes hachés¶
Dans un script, il n’y a personne pour fournir le mot de passe
à createuser
ou CREATE ROLE
. Ce qui suit permet de générer des hashs depuis le mot de passe, éventuellement sur une autre machine, pour qu’il ne passe jamais en clair ni ne risque de s’afficher en
clair dans les traces ni dans des vues système de PostgreSQL.
md5
¶
Le chiffrement md5
(celui par défaut, mais le plus faible) consiste à calculer la somme md5
du mot de passe concaténé au nom du rôle, puis « md5 » est ajouté devant. Ainsi deux utilisateurs de même mot de passe n’auront pas le même mot de passe chiffré. Cela nous donne en shell, avec un utilisateur u1 et un mot de passe « supersecret »:
scram-sha-256
¶
Générer soi-même des mots de passe chiffrés
en SCRAM-SHA-256 en-dehors de psql
est plus compliqué qu’avec MD5,
et les outils comme \password
s’appuient souvent sur les fonctions fournies par
la bibliothèque libpq
.
Cette dernière sert aussi de base à la bibliothèque python
psycopg3
et sa fonction
PGconn.encrypt_password()
Indépendamment de la libpq
,
il existe aussi un script python de Jonathan Katz (version 3.6 minimum)
que nous allons utiliser ici :
# Récupération de la librairie:
wget https://gist.githubusercontent.com/jkatz/e0a1f52f66fa03b732945f6eb94d9c21/raw/c0cf06c35da300866c36ad14309a88eb183aefc3/encrypt_password.py
On l’utilise dans un script de ce genre :
#!/usr/bin/python3
from encrypt_password import EncryptPassword
import sys
login = sys.argv[1]
mdp = sys.argv[2]
pw = EncryptPassword(
user=login,
password=mdp,
algorithm="scram-sha-256",
)
print( pw.encrypt().decode("utf-8"))
appelé en fournissant utilisateur et mot de passe :
Résultat :
SCRAM-SHA-256$4096:aBiN7rfgCWhPFsLI3yPOUA==$cCgRNSDprnrW7+8b6rFMB0RqMksF3ObbaSaus72lp2E=:Ph4fvVNcuBbFh/Da+jCMOrumU6a3BMIS4tRCwgAsRBU=
Ce hachage s’utilise dans CREATE ROLE … PASSWORD
ou ALTER ROLE
ainsi :