jeudi 11 mars 2010

gestion des mots de passe sous Karmic

Ubuntu Karmic 9.10 utilise à présent l'algorithme SHA512 pour le hashage de ses mots de passe (à la place de DES ou MD5). Cet article décrit l'implémentation de la méthode de chiffrement dans la librairie shadow d'Ubuntu.



déroulons le fil d'Ariane...

la commande passwd

Dans Ubuntu Karmic 9.10, la commande pour modifier le mot de passe utilisateur est « passwd ».

Jetons un oeil au code source du fichier /src/passwd.c dans le paquet shadow-* [1]:
/*
* Authenticate the user. The user will be prompted for their own
* password.
*/
(...)
cipher = pw_encrypt (clear, crypt_passwd);
(...)
la fonction pw_encrypt est définie dans le fichier lib/encrypt.c
char *pw_encrypt (const char *clear, const char *salt)
{
(...)
cp = crypt (clear, salt);
(...)
A ce stade, nous savons que la commande passwd fait appel à la fonction crypt().
Crypt() prend en arguments le mot de passe clair entré par l'utilisateur et un salt. Nous verrons après que le salt définit la méthode de chiffrement.

Comment ce salt est il construit?

la méthode de chiffrement par défaut est sha512

Par défaut, Ubuntu Karmic 9.10 utilise, pour ses mots de passe, la méthode de chiffrement SHA512 [2]. En effet, voici un extrait du fichier /etc/logins.def:

$ cat /etc/login.defs
(…)
#
# If set to MD5 , MD5-based algorithm will be used for encrypting password
# If set to SHA256, SHA256-based algorithm will be used for encrypting password
# If set to SHA512, SHA512-based algorithm will be used for encrypting password
# If set to DES, DES-based algorithm will be used for encrypting password (default)
# Overrides the MD5_CRYPT_ENAB option
#
# Note: It is recommended to use a value consistent with
# the PAM modules configuration.
#
ENCRYPT_METHOD SHA512
Ce fichier définit la variable d'environnement ENCRYPT_METHOD et lui attribue la valeur SHA512.

le salt est construit avec un préfixe défini selon la variable d'environnement ENCRYPT_METHOD


D'une part, la variable d'environnement ENCRYPT_METHOD est checkée dans la fonction Main() du source passwd.c précédemment vu:
if ((method = getdef_str ("ENCRYPT_METHOD")) == NULL) {
if (!getdef_bool ("MD5_CRYPT_ENAB")) {
pass_max_len = getdef_num ("PASS_MAX_LEN", 8);
}
} else {
if ( (strcmp (method, "MD5") == 0)
#ifdef USE_SHA_CRYPT
|| (strcmp (method, "SHA256") == 0)
|| (strcmp (method, "SHA512") == 0)
#endif /* USE_SHA_CRYPT */
)
(...)
}
Ainsi, la variable « method » de la structure « new_password » est initialisée avec « SHA512 » (toujours dans passwd.c):
static int new_password (const struct passwd *pw)
{
(...)
char *method;
D'autre part, un nouveau password est créé dans la fonction Main() de passwd.c en faisant appel aux fonctions pw_encrypt (vue précédemment) et crypt_make_salt:
/*
* Encrypt the password, then wipe the cleartext password.
*/
cp = pw_encrypt (pass, crypt_make_salt (NULL, NULL));
memzero (pass, sizeof pass);
La fonction crypt_make_salt est définie dans shadow-*/libmisc/salt.c. La méthode d'authentification y est aussi checkée:
const char *method;
(…)
{
method = getdef_str ("ENCRYPT_METHOD");
if (NULL == method) {
method = getdef_bool ("MD5_CRYPT_ENAB") ? "MD5" : "DES";
}
Nous voyons d'ailleurs que si la variable d'environnement ENCRYPT_METHOD n'était pas définie, la variable d'environnement MD5_CRYPT_ENAB serait alors checkée.

Ensuite, dans le cas SHA512, la fonction crypt_make_salt crée un salt en concaténant les caractères ', '6', ' puis un nombre pseudo aléatoire, et renvoie le tout.
if (0 == strcmp (method, "SHA512")) {
MAGNUM(result, '6');
strcat(result, SHA_salt_rounds((int *)arg));
salt_len = SHA_salt_size();

crypt() de la libc choisit l'algorithme de hashage en fonction du salt

Jetons un oeil à crypt().

Quelle est notre version de glibc?
$ ls /lib/libc-*
/lib/libc-2.11.1.so
Téléchargeons le source de la librairie glibc sur le site gnu.org [3]. La fonction crypt() est définie dans le fichier crypt/crypt-entry.c:
char * crypt (key, salt)
const char *key;
const char *salt;
{
#ifdef _LIBC
/* Try to find out whether we have to use MD5 encryption replacement. */
if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
return __md5_crypt (key, salt);

/* Try to find out whether we have to use SHA256 encryption replacement. */
if (strncmp (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0)
return __sha256_crypt (key, salt);

/* Try to find out whether we have to use SHA512 encryption replacement. */
if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
return __sha512_crypt (key, salt);
#endif

return __crypt_r (key, salt, &_ufc_foobar);
}

Conclusion

Sortis du labyrinthe, nous avons constaté que Ubuntu Karmic utilise sha512 par défaut, via la variable d'environnement ENCRYPT_METHOD dans le fichier /etc/login.defs.

la commande passwd est définie dans le source src/passwd.c de la libraire shadow-*. Passwd va créer un hash du mot de passe en clair entré par l'utilisateur dans la ligne de commande. Passwd appelle la fonction pw_encrypt(clair,salt).

Ce salt est créé avec la fonction crypt_make_salt() du source shadow-*/libmisc/salt.c. Cette dernière prend en compte la variable d'environnement ENCRYPT_METHOD.

La fonction pw_encrypt de passwd fait appel à la fonction crypt de la libc.

La fonction crypt choisit la méthode de chiffrement en fonction du préfixe du salt.


John the Ripper ne prend pas en compte SHA512 pour l'instant... A vos scripts!

références

1) détails du paquet passwd Ubuntu - http://packages.ubuntu.com/karmic/passwd
2) manuel libc – fonction crypt() - http://www.gnu.org/s/libc/manual/html_node/crypt.html
3)sources libc - http://www.gnu.org/software/libc/

Aucun commentaire:

Enregistrer un commentaire