9. Tester la protection des échanges NFS

Cette section présente les tests de montage et les captures de trafic qui ont été réalisés avant la sécurisation des échanges NFS. Il s'agit à présent de caractériser les effets du durcissement de la configuration sur l'interception et l'usurpation.

9.1. Identifier les paramètres de sécurité lors de l'automontage

L'automontage du répertoire utilisateur doit se faire lors de la connexion au compte utilisateur etu-nfs que l'on a créé manuellement sur le serveur et sur le client NFS.

Q108.

Comment tester la connexion au compte etu-nfs depuis le serveur ?

Ouvrir une connexion SSH sur le client depuis le serveur.

ssh etu-nfs@nfs-client
(etu-nfs@nfs-client) Password:

Affichez le répertoire courant pour confirmer qu'il s'agit bien de l'automontage : /ahome/etu-nfs/.

pwd
/ahome/etu-nfs

Affichez les propriétés du montage NFS et identifiez les paramètres relatifs à la sécurité.

mount | grep nfs
nfs-server.lab.local:/home/etu-nfs on /ahome/etu-nfs type nfs4 (rw,nosuid,nodev,noexec,relatime,vers=4.2,
    rsize=131072,wsize=131072,namlen=255,hard,fatal_neterrors=none,proto=tcp6,timeo=600,retrans=2,
    sec=krb5p,xprtsec=mtls,
    clientaddr=2001:678:3fc:65:baad:caff:fefe:6,local_lock=none,addr=2001:678:3fc:65:baad:caff:fefe:5,_netdev)

La liste des paramètres est très longue, mais on repère la version Kerberos ainsi que l'utilisation du protocole TLS.

Nous avons la confirmation que les fonctions de sécurisation des transactions NFS sont actives.

9.2. Analyser un appel au service portmapper

Nous reprenons ici la capture du trafic entre le client et le serveur NFS lors de l'utilisation des commandes qui utilisent le port sunrpc/111 comme rpcinfo ou showmount.

Q109.

Comment lancer une capture de trafic avec tshark sur le serveur avant d'exécuter la commande rpcinfo -s nfs-server sur le client ?

Est-ce que ces échanges sont sécurisés ? Comment interpréter les résultats ?

  1. Lancez la capture de trafic côté serveur NFS.

    tshark -i enp0s1 -f "host 2001:678:3fc:65:baad:caff:fefe:6" -w nfs-sec-rpcinfo.pcap

    L'adresse d'hôte sélectionnée est celle du client NFS.

  2. Lancez la requête RPC au portmapper avec la commande rpcinfo -s nfs-server côté client.

    rpcinfo -s nfs-server
       program version(s) netid(s)                         service     owner
        100000  2,3,4     local,udp,tcp,udp6,tcp6          portmapper  superuser
        100024  1         tcp6,udp6,tcp,udp                status      104
        100005  3,2,1     tcp6,udp6,tcp,udp                mountd      superuser
        100003  4,3       tcp6,tcp                         nfs         superuser
        100227  3         tcp6,tcp                         nfs_acl     superuser
        100021  4,3,1     tcp6,udp6,tcp,udp                nlockmgr    superuser
  3. Arrêtez la capture côté serveur avec Ctrl+C.

Affichez la liste des trames capturées.

tshark -r nfs-sec-rpcinfo.pcap
1 0.000000000 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TCP 94 52846 → 111 [SYN] Seq=0 Win=64800 Len=0 MSS=1440 SACK_PERM TSval=2344535586 TSecr=0 WS=128
 2 0.000041863 2001:678:3fc:65:baad:caff:fefe:5 → 2001:678:3fc:65:baad:caff:fefe:6 TCP 94 111 → 52846 [SYN, ACK] Seq=0 Ack=1 Win=64260 Len=0 MSS=1440 SACK_PERM TSval=1771129017 TSecr=2344535586 WS=128
 3 0.000524446 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TCP 86 52846 → 111 [ACK] Seq=1 Ack=1 Win=64896 Len=0 TSval=2344535587 TSecr=1771129017
 4 0.000760423 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 Portmap 130 V3 DUMP Call
 5 0.000774930 2001:678:3fc:65:baad:caff:fefe:5 → 2001:678:3fc:65:baad:caff:fefe:6 TCP 86 111 → 52846 [ACK] Seq=1 Ack=45 Win=64256 Len=0 TSval=1771129017 TSecr=2344535587
 6 0.001370718 2001:678:3fc:65:baad:caff:fefe:5 → 2001:678:3fc:65:baad:caff:fefe:6 Portmap 2554 V3 DUMP Reply (Call In 4)
 7 0.001730994 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TCP 86 52846 → 111 [ACK] Seq=45 Ack=2469 Win=69888 Len=0 TSval=2344535588 TSecr=1771129018
 8 0.002623609 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TCP 86 52846 → 111 [FIN, ACK] Seq=45 Ack=2469 Win=69888 Len=0 TSval=2344535589 TSecr=1771129018
 9 0.002689252 2001:678:3fc:65:baad:caff:fefe:5 → 2001:678:3fc:65:baad:caff:fefe:6 TCP 86 111 → 52846 [FIN, ACK] Seq=2469 Ack=46 Win=64256 Len=0 TSval=1771129019 TSecr=2344535589
10 0.002812963 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TCP 86 52846 → 111 [ACK] Seq=46 Ack=2470 Win=69888 Len=0 TSval=2344535589 TSecr=1771129019

Les échanges RPC qui utilisent le port sunrpc/111 ne sont pas protégés.

Lorsque NFS est configuré pour utiliser TLS via tlshd, tout service s'exécutant derrière tlshd voit son trafic RPC protégé par TLS.

Comme rpcinfo ne peut pas se connecter au point de terminaison RPC encapsulé dans TLS, il communique en clair avec les points de terminaison traditionnels non TLS (comme portmap/rpcbind s'exécutant sans tlshd).

9.3. Capturer le trafic entre le client et le serveur NFS

On reprend la même capture de trafic que celle réalisée lors de la question Q : Q89.

Q110.

Comment réaliser une capture de trafic réseau côté serveur pendant que l'utilisateur génère un fichier texte dans son répertoire utilisateur ?

  1. Capturez le trafic côté serveur avec tshark.

  2. Créez un fichier texte dans le répertoire utilisateur /ahome/etu-nfs/ côté client.

  3. Affichez un extrait de charge utile présent dans le fichier de capture côté serveur.

  1. Capturez le trafic avec la même syntaxe pour la commande tshark. Changez simplement le nom du fichier de capture.

    tshark -i enp0s1 -f "host 2001:678:3fc:65:baad:caff:fefe:6" -w nfs-sec-man.pcap
  2. Lancez la même commande de génération de fichier texte côté client NFS avec l'identité etu-nfs depuis son répertoire utilisateur.

    man man > man.txt
  3. Revenez côté serveur et arrêtez la capture de trafic avec Crtl+C.

    Listez les trames capturées dans le fichier nfs-sec-man.pcap sans le filtre de protocole -Y nfs.

    tshark -r nfs-sec-man.pcap
     1 0.000000000 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TLSv1.2 352 Application Data
     2 0.000289635 2001:678:3fc:65:baad:caff:fefe:5 → 2001:678:3fc:65:baad:caff:fefe:6 TLSv1.2 352 Application Data
     3 0.000897117 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TCP 86 673 → 2049 [ACK] Seq=267 Ack=267 Win=537 Len=0 TSval=2347950253 TSecr=1774543683
     4 0.001232074 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TLSv1.2 432 Application Data
     5 0.001401592 2001:678:3fc:65:baad:caff:fefe:5 → 2001:678:3fc:65:baad:caff:fefe:6 TLSv1.2 564 Application Data
     6 0.001910048 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TLSv1.2 400 Application Data
     7 0.004035351 2001:678:3fc:65:baad:caff:fefe:5 → 2001:678:3fc:65:baad:caff:fefe:6 TLSv1.2 496 Application Data
     8 0.046862987 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TCP 86 673 → 2049 [ACK] Seq=927 Ack=1155 Win=537 Len=0 TSval=2347950299 TSecr=1774543686
     9 0.079854964 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TLSv1.2 7226
    10 0.079855475 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TCP 7226 673 → 2049 [PSH, ACK] Seq=8067 Ack=1155 Win=537 Len=7140 TSval=2347950331 TSecr=1774543686
    11 0.091014106 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TCP 1514 673 → 2049 [ACK] Seq=15207 Ack=1155 Win=537 Len=1428 TSval=2347950343 TSecr=1774543686
    12 0.123207572 2001:678:3fc:65:baad:caff:fefe:5 → 2001:678:3fc:65:baad:caff:fefe:6 TCP 86 2049 → 673 [ACK] Seq=1155 Ack=16635 Win=440 Len=0 TSval=1774543806 TSecr=2347950331
    13 0.123638355 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TLSv1.2 14366 Application Data
    14 0.123679943 2001:678:3fc:65:baad:caff:fefe:5 → 2001:678:3fc:65:baad:caff:fefe:6 TCP 86 2049 → 673 [ACK] Seq=1155 Ack=30915 Win=378 Len=0 TSval=1774543806 TSecr=2347950375
    15 0.123698705 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TLSv1.2 9568 Application Data, Application Data
    16 0.123710890 2001:678:3fc:65:baad:caff:fefe:5 → 2001:678:3fc:65:baad:caff:fefe:6 TCP 86 2049 → 673 [ACK] Seq=1155 Ack=40397 Win=336 Len=0 TSval=1774543806 TSecr=2347950375
    17 0.126918761 2001:678:3fc:65:baad:caff:fefe:5 → 2001:678:3fc:65:baad:caff:fefe:6 TLSv1.2 328 Application Data
    18 0.127283594 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TCP 86 673 → 2049 [ACK] Seq=40397 Ack=1397 Win=537 Len=0 TSval=2347950379 TSecr=1774543809
    19 0.129786532 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TLSv1.2 356 Application Data
    20 0.129942990 2001:678:3fc:65:baad:caff:fefe:5 → 2001:678:3fc:65:baad:caff:fefe:6 TLSv1.2 364 Application Data
    21 0.175012780 2001:678:3fc:65:baad:caff:fefe:6 → 2001:678:3fc:65:baad:caff:fefe:5 TCP 86 673 → 2049 [ACK] Seq=40667 Ack=1675 Win=537 Len=0 TSval=2347950427 TSecr=1774543812

    Dans la liste ci-dessus, on identifie l'utilisation de TLS, ce qui montre que le trafic entre le client et le serveur NFS est bien chiffré de bout en bout.

  4. Affichez le contenu d'une trame pour illustrer le fait que les données sont inexploitables.

    tshark -r nfs-sec-man.pcap -Y "frame.number == 5" -T fields -e tls.app_data
    7280bc6f255b74b6537ce42fb2f3b47bcf9aca8abc78773362811f90ea13a7b116cb3d7
    838fd32e297d97fec2982fca3795baa78a9b393a1dcd1f145b9ed661c3b9f056b051a85bc21245b
    ba6a1b7ffb2a7dde422618a083417ae408c559be5aaff4c6678293cc0acfa445d02ade4cca010f6
    d4ade9ae63506ad79e379f83538ab22b55646229a29720c009b935712792d17376744ffc2a71d54
    281ffb53966d1f78ac8315e4752a7e5f3f5381e4013afb2d66ee2d8f06eecd572846d8086d07ac7
    9a30db370871a2ab2d1652608613d005333a1d0e2c339135f04da905068bed44372b25a05e6bd78
    dd566e9bd17ddca6608e20758716569407ea044b7342ce39205fd581eaf0b49c79707762aa0af9c
    64fb09e119dcf8a75e6c6f9ee82cbe02b856ffe1baa8b9f02d72e7fc6a5410a5966364bea4a83b6
    f6bb01982a94d9045fab462e42a384575c6d58d1e3666af975cfc42af787287cc625f337bc3ec13
    af09799ade005cac6c9e7af1fea3f3f4b886d1301ef23af9c47e35be1d0f5142c2551cde08ca04b
    1332149c915018a78184b911755640a623345072d060adbf51b6b0cbe6a368d4897ea4c0b4b1d30
    148ae4aef77c44187344b6b67546992681bc5d67a5b0e57ef83ff2249d702d510344eee063b8289
    dac0cd

Les résultats de cette section illustrent l'efficacité du renforcement de la sécurité NFS. Grâce à la mise en œuvre de Kerberos et de TLS, les échanges entre le client et le serveur sont désormais chiffrés et protégés, ce qui réduit considérablement les risques d'interception des données échangées et d'usurpation d'identité.

Il convient toutefois de noter une exception concernant le service portmapper, pour lequel le chiffrement de bout en bout n'est pas assuré. Ce défaut peut être compensé par une politique de filtrage qui restreint l'utilisation de ce service aux seuls hôtes habilités à diagnostiquer le fonctionnement des services NFS.

9.4. Analyser les échanges Kerberos depuis le KDC

Lors de la connexion avec l'identité etu-nfs sur le client NFS, kerberos doit vérifier les identités de l'hôte client et de l'utilisateur.

Pour valider le fonctionnement de l'authentification Kerberos, on peut consulter les journaux systèmes.

Q111.

Comment valider le fonctionnement du protocole Kerberos et l'utilisation correcte des principaux ?

Consultez les journaux du services KDC et vérifiez la correspondance avec les principaux définis dans la Section 8, « Sécuriser les transactions NFS ».

Commencez par une consultation directe du journal du service krb5-kdc.

journalctl -u krb5-kdc

Repérez les messages d'échanges dans lesquels les principaux sont référencés et isolez les dans un fichier texte. Voici un exemple qui englobe le démarrage du service dans les 28 dernières lignes du journal :

journalctl -u krb5-kdc -n 28  > krb5-journal.txt
cat krb5-journal.txt | sed 's/^.\{16\}//'
 srvr (krb5kdc)[700]: krb5-kdc.service: Referenced but unset environment variable evaluates to an empty string: DAEMON_ARGS
 srvr krb5kdc[700]: preauth spake failed to initialize: No SPAKE preauth groups configured
 srvr krb5kdc[700]: setting up network...
 srvr krb5kdc[700]: Setting up UDP socket for address 0.0.0.0.750
 srvr krb5kdc[700]: Setting pktinfo on socket 0.0.0.0.750
 srvr krb5kdc[700]: Setting up UDP socket for address ::.750
 srvr krb5kdc[700]: setsockopt(9,IPV6_V6ONLY,1) worked
 srvr krb5kdc[700]: Setting pktinfo on socket ::.750
 srvr krb5kdc[700]: Setting up UDP socket for address 0.0.0.0.88
 srvr krb5kdc[700]: Setting pktinfo on socket 0.0.0.0.88
 srvr krb5kdc[700]: Setting up UDP socket for address ::.88
 srvr krb5kdc[700]: setsockopt(11,IPV6_V6ONLY,1) worked
 srvr krb5kdc[700]: Setting pktinfo on socket ::.88
 srvr krb5kdc[700]: Setting up TCP socket for address 0.0.0.0.88
 srvr krb5kdc[700]: Setting up TCP socket for address ::.88
 srvr krb5kdc[700]: setsockopt(13,IPV6_V6ONLY,1) worked
 srvr krb5kdc[700]: set up 6 sockets
 srvr krb5kdc[734]: commencing operation
 srvr systemd[1]: Started krb5-kdc.service - Kerberos 5 Key Distribution Center.
 srvr krb5kdc[734]: AS_REQ (2 etypes {aes256-cts-hmac-sha1-96(18),
    aes128-cts-hmac-sha1-96(17)}) 2001:678:3fc:65:baad:caff:fefe:6:
    NEEDED_PREAUTH: etu-nfs@LAB.LOCAL for krbtgt/LAB.LOCAL@LAB.LOCAL, Additional
    pre-authentication required
 srvr krb5kdc[734]: AS_REQ (2 etypes {aes256-cts-hmac-sha1-96(18),
    aes128-cts-hmac-sha1-96(17)}) 2001:678:3fc:65:baad:caff:fefe:6: ISSUE:
    authtime 1759559434, etypes {rep=aes256-cts-hmac-sha1-96(18),
    tkt=aes256-cts-hmac-sha1-96(18), ses=aes256-cts-hmac-sha1-96(18)},
    etu-nfs@LAB.LOCAL for krbtgt/LAB.LOCAL@LAB.LOCAL
 srvr krb5kdc[734]: AS_REQ (2 etypes {aes256-cts-hmac-sha1-96(18),
    aes128-cts-hmac-sha1-96(17)}) 2001:678:3fc:65:baad:caff:fefe:6:
    NEEDED_PREAUTH: nfs/nfs-client.lab.local@LAB.LOCAL for
    krbtgt/LAB.LOCAL@LAB.LOCAL, Additional pre-authentication required
 srvr krb5kdc[734]: AS_REQ (2 etypes {aes256-cts-hmac-sha1-96(18),
    aes128-cts-hmac-sha1-96(17)}) 2001:678:3fc:65:baad:caff:fefe:6: ISSUE:
    authtime 1759559434, etypes {rep=aes256-cts-hmac-sha1-96(18),
    tkt=aes256-cts-hmac-sha1-96(18), ses=aes256-cts-hmac-sha1-96(18)},
    nfs/nfs-client.lab.local@LAB.LOCAL for krbtgt/LAB.LOCAL@LAB.LOCAL
 srvr krb5kdc[734]: TGS_REQ (2 etypes {aes256-cts-hmac-sha1-96(18),
    aes128-cts-hmac-sha1-96(17)}) 2001:678:3fc:65:baad:caff:fefe:6: ISSUE:
    authtime 1759559434, etypes {rep=aes256-cts-hmac-sha1-96(18),
    tkt=aes256-cts-hmac-sha1-96(18), ses=aes256-cts-hmac-sha1-96(18)},
    nfs/nfs-client.lab.local@LAB.LOCAL for nfs/nfs-server@LAB.LOCAL
 srvr krb5kdc[734]: TGS_REQ (2 etypes {aes256-cts-hmac-sha1-96(18),
    aes128-cts-hmac-sha1-96(17)}) 2001:678:3fc:65:baad:caff:fefe:6: ISSUE:
    authtime 1759559434, etypes {rep=aes256-cts-hmac-sha1-96(18),
    tkt=aes256-cts-hmac-sha1-96(18), ses=aes256-cts-hmac-sha1-96(18)},
    etu-nfs@LAB.LOCAL for nfs/nfs-server@LAB.LOCAL
 srvr krb5kdc[734]: AS_REQ (2 etypes {aes256-cts-hmac-sha1-96(18),
    aes128-cts-hmac-sha1-96(17)}) 2001:678:3fc:65:baad:caff:fefe:6:
    CLIENT_NOT_FOUND: etu@LAB.LOCAL for krbtgt/LAB.LOCAL@LAB.LOCAL, Client not
    found in Kerberos database
 srvr krb5kdc[734]: AS_REQ (2 etypes {aes256-cts-hmac-sha1-96(18),
    aes128-cts-hmac-sha1-96(17)}) 2001:678:3fc:65:baad:caff:fefe:6:
    NEEDED_PREAUTH: etu-nfs@LAB.LOCAL for krbtgt/LAB.LOCAL@LAB.LOCAL, Additional
    pre-authentication required
 srvr krb5kdc[734]: AS_REQ (2 etypes {aes256-cts-hmac-sha1-96(18),
    aes128-cts-hmac-sha1-96(17)}) 2001:678:3fc:65:baad:caff:fefe:6: ISSUE:
    authtime 1759559760, etypes {rep=aes256-cts-hmac-sha1-96(18),
    tkt=aes256-cts-hmac-sha1-96(18), ses=aes256-cts-hmac-sha1-96(18)},
    etu-nfs@LAB.LOCAL for krbtgt/LAB.LOCAL@LAB.LOCAL

Q112.

Comment interpréter les messages kerberos relevés dans le journal du service KDC ?

Analysez les demandes et les réponses de la séquence d’authentification pour le compte etu-nfs et le client nfs-client.

Décrivez la séquence d'authentification observée :

  • Le KDC reçoit d'abord une requête AS_REQ du principal etu-nfs@LAB.LOCAL qui demande un TGT (Ticket Granting Ticket) pour accéder à Kerberos.

  • Il demande ensuite une pré-authentification (NEEDED_PREAUTH). C'est le comportement standard de Kerberos pour vérifier que le client possède la clé du principal.

  • Une fois la pré-authentification fournie (par mot de passe ou keytab), le KDC délivre le TGT à etu-nfs@LAB.LOCAL (ligne ISSUE avec authtime, rep=tkt=ses=AES256-CTS-HMAC-SHA1-96).

  • Le même schéma se reproduit pour le principal nfs/nfs-client.lab.local@LAB.LOCAL, obtenu via une entrée keytab sur l'hôte client NFS.

  • Ensuite, des requêtes TGS_REQ sont émises : ces principaux demandent un ticket de service pour accéder au service nfs/nfs-server@LAB.LOCAL via le KDC.

  • Le KDC émet alors un ticket de service pour chaque principal, validant ainsi leur authentification et leur autorisation d'accès au partage NFS via Kerberos (lignes TGS_REQ avec ISSUE).

  • Une tentative de connexion par le compte etu@LAB.LOCAL échoue, car il n'existe pas dans la base Kerberos (CLIENT_NOT_FOUND).