Master SAR 2006-2007, Université Pierre & Marie Curie. Emmanuel Saint-James, Fabrice Legond-Aubry. [retour à l'index des TD]

Administration et Architecture des Systèmes, TD 4

L'authentification sous Linux

1   Qualité d'un mot de passe

Il existe plusieurs solutions pour vérifier la qualité d'un mot de passe.

1.1   John the ripper

La première solution est de tester à postiriori les mots de passe stockés dans le système. Un des programmes les plus utilisé (parmis les nombreux existant) est "John the Ripper". Il permet de faire des attaques par dictionnaires et mutations sur les fichiers de mot de passe.

Rappel: les fichiers de mots de passe ne stockent pas les mots de passe mais le résultat de la transformation du mot de passe par une fonction a sens unique. John The Ripper support plusieurs fonctions à sens uniques (MD5, crypt, LM).

Question

Récuperez les fichiers passwd et shadow. Recréez un fichier passwd contenant les mots de passe shadow et les informations gecos en utilisant l'utilitaire unshadow de john. Créer un dictionnaire global en utilisant les dictionnaire de John et de cracklib.

1.2   Cracklib

Déontologiquement, la vérification du mot de passe des utilisateurs reste quand même limite. A la place de tester les mots de passes déjà stockés dans le système, il reste possible de forcer les utilisateurs à saisir des mots de passe corrects.

Pour cela, il existe le programme cracklib (ainsi que sa librairie pam_cracklib). Ce programme permet de vérifier le mot de passe.

Question

Faites foncionner le cracklib_test pour tester les mots de passe saisie par les utilisateurs. Utilisez pour cela le dictionnaire généré précédemment.

Il existe une librairie pam_cracklib pour pam qui permet de vérifier la validiter du mot de passe. Quelle session du pam.d faudrait-il modifier pour ajouter cette librairie ?

2   Le système PAM

Voir dans /etc/pam.d et regarder les différents fichiers.

Dans l'ordre pour faire de l'authentification pam, il faut utiliser les fonctions
  • pam_start qui va initialisation un handler d'authentification (pam_handle_t). Vous utiliserez la structure pam_conv suivante :

    static struct pam_conv conv = {
       misc_conv,
       NULL
    };
    
  • pam_set_item pour fixer les paramètres de l'authentification

  • pam_authenticate pour effectuer l'authentification (le handler mémorisera les informations d'authentification).

  • pam_acct_mgmt pour savoir si le mot de passe doit être changé.

  • pam_setcred pour fixer les droits utilisateurs. Rappel: Seul root peut changer d'identité (voir les bits suid de passwd, su, ...).

Question

Ecrire un programme qui utilise le service PAM pour s'authentifier et exécuter la commande passée en paramètre avec les droits de l'utilisateur donné en paramètre.

3   L'authentification X-Window

La Xlib est la bibliothèque graphique standard d'Unix. Une de ses originalités est d'etre fondée sur une architecture client / serveur distribuée, ce qui permet à tout client Internet de demander l'ouverture de fenetres et autres services apparentés sur a priori n'importe quelle machine du réseau. Cette généralité (qui inclut meme le verrouillage du clavier du poste concerné !) est évidemment tempérée par une authentification invisible mais bien réelle. La présente séance consiste à expliciter cette authentification, afin de comprendre les mécanismes mis en jeu et leurs éventuelles limitations.

En trouvera en annexe un fichier main.c ainsi qu'un makefile référençant celui-ci et deux fichiers request.c et receive.c qu'il s'agit d'écrire, ainsi qu'un petit shell-script de test. On rappelle que dans un makefile, un but est un symbole au début d'une ligne comportant un deux-points, et les sources ce qui suit ce deux-points. Le but s'obtient des sources en exécutant les commandes shell écrites dans les lignes suivantes, jusqu'à rencontre d'une ligne ne commençant pas par une tabulation. Le symbole % permet d'énoncer plusieurs dépendances à la fois ; en particulier, %.o : %.c énonce que tout but suffixé par .o a pour source le fichier homonyme de suffixe .c. Les variables @ et &lt ; désignent respectivement le but courant et sa première source.

Le programme C lance une fonction main tentant une connexion avec le serveur X-window donné en argument, ou à défaut au serveur local standard (adresse 127.0.0.1, port 6000). Une fonction showbuffer est incluse pour visualiser les messages transmis, ainsi qu'une fonction peroraison pour déclencher des messages d'erreur. Le protocole X-window n'est ni textuel ni synchrone : les clients envoient des flux d'octets structurés différement selon les requêtes (et selon leur byte-ordering), et prennent connaissance des réponses ou des notifications d'événements quand ils l'estiment nécessaire.

3.1   Ouverture

Écrire la fonction request (dans un fichier C homonyme), invoquée par main après un connect réussi. Son rôle est d'envoyer au serveur la requête d'ouverture, ainsi structurée :

Numéro Nombre Valeur Description
0 1 B ou l B pour gros-boutien, l pour petit-boutien
1 1 ; inutilisé
2 2 [1,11] numéro de version
4 2 ; numéro de sous-version
6 2 n longueur du nom de la méthode d'identification
8 2 d longueur de la clé d'identification
10 2 ; inutilisé
12 n ; nom de la méthode d'identification
12+n c(n) ; cadrage pour alignement
12+n+c(n) d ; clé d'identification
12+n+c(n)+d c(d) ; cadrage pour alignement

Question

Ecrire une définition provisoire de receive comme ne faisant rien, afin de tester en l'état, sans donner aucun argument au binaire produit.

3.2   Repérage d'erreur

La fonction receive, invoquée par main, va recevoir un flux commençant par les 8 octets suivants :

Numéro Nombre Valeur Description
0 1 0 ou 1 erreur ou réusite
1 1 n longueur du message d'erreur, inutilisé sinon
2 2 [1,11] numéro de version
4 2 ; numéro de sous-version
6 2 n/4+((n%4)!=0) longueur en mots de 32 bits de la suite

Question

Écrire d'abord une version réduire de la fonction receive, testant si les 8 octets reçus dénotent une erreur, et si oui, affichant le message d'erreur (ce sont les octets suivants, moins les octets de cadrage).

3.3   Répérage de la réussite

En cas de réussite de la connexion, les 8 premiers octets sont suivis des 32 suivants :

Numéro Nombre Valeur Description
0 4 ; numéro de série
4 4 < ; 2^29 identificateur de création
8 4 plus de 18 '1' consécutifs masque de création
12 4 ; nombre de mouvements mémorisés
16 2 c longueur du nom du constructeur
18 2 ; longueur maximale d'une requête
20 1 n nombre d'écrans
21 1 ; nombre de formats
22 1 ; ordre des octets
23 1 ; ordre des bits
24 1 ; format des bits
25 1 ; cadrage des bits
26 1 ; plus petit code des touches
27 1 ; plus grand code des touches
28 4 ; inutilisé
32 c ; nom du constructeur
32+c ; ; descriptions des formats et écrans
       

Question

Compléter la fonction receive pour qu'en cas de réussite, elle affiche le nom du constructeur et le nombre d'écran.

3.4   Méthode d'authentification

Pour donner à ce programme les arguments nécessaires à une connexion réussie, il faut connaître la méthode d'identification et sa clé. Elles se trouvent dans le fichier .Xauthority. Les clés étant des valeurs binaires, le fichier est peu lisible, aussi on utilisera la commande xauthlist.

Question

Repérer votre dispositif dans le résultat, et utiliser les informations associées pour réussir votre connexion (attention ! il faut convertir en binaire les valeurs hexadécimales affichées en ascii par xauth).

3.5   Clé d'identification

Question

Écrire le script etquecasaute qui produit automatiquement les arguments nécessaires au programme. Consulter la documentation sur xauth pour cela, et employer l'utilitaire sed pour effacer les informations inutiles.

3.6   Limitations

A ce stade, le programme écrit est assez proche de la commande xdpyinfo, il est inutile d'aller plus loin dans cette direction. Discuter en revanche les limites de cette méthode :

  1. en ce qui concerne les droits sur le fichier .Xauthority
  2. en ce qui concerne la surveillance du réseau par un tiers.

Question

En conclure qu'il est de nos jour impératif d'utiliser l'option -X de la commande ssh.