Hardening consulting

Se connecter avec une carte à puce dans FreeRDP

Dans (le futur) FreeRDP 3.0, il y a le support pour le smartcard logon, sur lequel j'ai pas mal travaillé, voyons un petit peu ce qu'il en est.


Support smartcard

On commence par vérifier qu'on voit bien la smartcard, dans mon cas il s'agit d'un yubikey(TM):

$ opensc-tool -l
# Detected readers (pcsc)
Nr.  Card  Features  Name
0    Yes             Yubico YubiKey OTP+FIDO+CCID 00 00

Tant qu'à faire, on vérifie aussi qu'il y a bien ce qu'il faut sur la carte pour fait un logon:

$ pkcs11-tool -O
Using slot 0 with a present token (0x0)
Private Key Object; RSA 
  label:      CARD AUTH key
  ID:         04
  Usage:      decrypt, sign, unwrap
  Access:     sensitive, always sensitive, never extractable, local
Public Key Object; RSA 2048 bits
  label:      CARD AUTH pubkey
  ID:         04
  Usage:      encrypt, verify, wrap
  Access:     none
Certificate Object; type = X.509 cert
  label:      Certificate for Card Authentication
  subject:    DN: DC=com, DC=hardening2, CN=Users, CN=david
  ID:         04
Data object 466566400
  label:          'Card Capability Container'
  application:    'Card Capability Container'
  app_id:         2.16.840.1.101.3.7.1.219.0
  flags:          <empty>

[...]

Data object 466567456
  label:          'Discovery Object'
  application:    'Discovery Object'
  app_id:         2.16.840.1.101.3.7.2.96.80
  flags:          <empty>
Profile object 466573616
  profile_id:          '3'

Ce qu'il faut trouver c'est la clé (Private Key Object; RSA), et le certificat associé (Certificate Object; type = X.509 cert).

Et enfin on vérifie que la clé et le certificat sont bien vus par FreeRDP:

$ ./output-linux/client/X11/xfreerdp /list:smartcard
smartcard reader detected, listing 1 certificates:
0: DC = com, DC = hardening2, CN = Users, CN = david
        * CSP: Microsoft Base Smart Card Crypto Provider
        * reader: Yubico YubiKey OTP+FIDO+CCID 00 00
        * slotId: 0
        * pkinitArgs: PKCS11:module_name=opensc-pkcs11.so:slotid=0
        * containerName: 8d40a038-e120-24ba-77ab-0237715fc101
        * UPN: david@hardening2.com

A noter que pour l'instant FreeRDP ne supporte que les certificats avec des clés RSA, pas les courbes elliptiques. Si d'aventure l'accès à la smartcard se fait avec un librairie propriétaire, on peut passer l'option avec /kerberos:pkcs11-module:<chemin vers le .so>. Dans le cas ou il y a plusieurs certificats ou plusieurs smartcard, en utilisant les options /u:<user> ou /d:<domain>, un filtrage pour cet utilisateur ou ce realm sont opérés.

Si cette étape ne liste pas le certificat, ce n'est pas la pein d'aller plus loin, FreeRDP n'arrivera pas à vous faire une smartcard logon.

Pour que le logon marche complètement, il faut absolument qu'on arrive à calculer le containerName, sinon ça connectera en RDP mais ça redemandera le code PIN à la connexion. Pour l'instant dans FreeRDP, nous savons calculer ça pour les cartes qui répondent à la norme PIV (quasiment toute les cartes).

Configuration Kerberos

Quand on fait un smartcard logon, en fait on établi une connexion en Kerberos avec la carte à puce à travers des paquets NLA (du CredSSP à l'intérieur). Donc commençons par vérifier que tout le kerberos marche en testant un logon "à la main".

Dans mon cas, mon realm s'appelle HARDENING2.COM, le controlleur de domaine windows correspondant est sur la machine dc.hardening2.com, et je vais me logguer en tant que david . Comme on fait du kerberos, on n'oubliera pas l'emploi des majuscules pour le realm.

Sans configuration, si on tape kinit david@HARDENING2.COM, sauf si le DNS est correctement configuré, ça ne devrait pas marcher car la machine locale ne sait pas comment joindre le royaume HARDENING2.COM. Il faut donc configurer ça dans le fichier /etc/krb5.conf:

HARDENING2.COM = {
    kdc = 192.168.125.2
    admin_server = 192.168.125.2

    pkinit_anchors = FILE:/etc/hardening2-ca.pem
    pkinit_eku_checking = kpServerAuth
    pkinit_kdc_hostname = dc.hardening2.com 
}
  • les champs kdc et admin_server sont les adresses ou les noms qualifiés du controlleur de domaine ;
  • le champs pkinit_anchors donne le chemin vers les certificats de la ou des autorités de certification délivrant les certificats sur les smartcards (ça peut aussi être de la forme DIR:répertoire). C'est à récupérer sur le contolleur de domaine soit dans les clicodromes de gestion de la PKIs, soit dans l'interface web d'enrôlement quand elle est installée. Ce n'est pas toujours facile ;
  • d'expérience on est souvent obligé de préciser pkinit_kdc_hostname ;

Note: je ne détaille pas comment configurer la partie windows pour le smartcard logon, ou comment créer les certificats et les mettre sur la carte à puce. Je peux juste dire que c'est tout sauf simple, mais le web regorge de suite d'instructions à suivre (qui ne marchent pas toujours).

Et du coup une fois cette configuration faite, on doit pouvoir tenter une connexion smartcard (il faut taper son code PIN):

$ kinit -X X509_user_identity='PKCS11:opensc-pkcs11.so' david@HARDENING2.COM
Users                            PIN: ***********

On vérifie qu'on a bien un TGT:

$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: david@HARDENING2.COM

Valid starting       Expires              Service principal
04/10/2023 14:42:34  05/10/2023 00:42:34  krbtgt/HARDENING2.COM@HARDENING2.COM
        renew until 05/10/2023 14:42:32

Quand on essaye de debugger la configuration kerberos, il est bien utile de positionner la variable d'environnement KRB5_TRACE=/dev/stdout, ça permet d'augmenter la verbosité de la libkrb5 et on voit où ça échoue.

Connection avec FreeRDP

Une fois que tout ça fonctionne, l'essentiel du travail est fait. Avec un seul certificat dans une seule carte à puce FreeRDP va déduire la majorité des paramètres (le nom de l'utilisateur, le royaume kerberos, lecteur, ...):

$ ./output/client/X11/xfreerdp /v:dc2.hardening2.com /smartcard-logon:pin:XXXXXX /sec:nla
....

Conclusion

Avec FreeRDP 3, on a aussi le support du NLA coté serveur avec Kerberos (par exemple pour le shadow server), je ferais sans doute un article pour détailler comment on configure ça. Ça peut permettre d'avoir la connection au shadow server faite en NLA avec du kerberos, et même avec une authentification smartcard.