Ellendhel's Blog

CryptographieConfiguration renforcée pour OpenSSH

Si vous vous intéressez un minimum à la sécurité informatique, vous êtes probablement familier avec les notions de configuration renforcée (ou durcissement, hardening en anglais) et avec les scanners de vulnérabilité. Le principe est d'établir une configuration garantissant un certain niveau de sécurité et d'utiliser un logiciel pour vérifier qu'aucune faille connue ne soit présente.

La définition des options de configuration peut être délicate, selon votre connaissance du logiciel et de multiples options possibles. La situation devient encore plus complexe pour ce qui peut toucher à la cryptographie.

C'est là qu'un scanner de vulnérabilité s’avérera utile : les résultats pourront indiquer quelles options de configuration présentent des risques et, éventuellement, comment y remédier.

Prenons le cas d'OpenSSH. SSH est utilisé quotidiennement, et les guides de configuration recommandent le plus souvent de désactiver l'accès pour le compte root et d'utiliser des clés d'authentification (excellentes choses en soi) mais un scanner relèvera des points obscurs tel que l'utilisation du mode d'opération CBC (Cipher Block Chaining, chiffrement par enchaînement de blocs). Un administrateur système ayant peu de connaissance en cryptographie sera sans doute perplexe ; d'autant qu'aucune option "disable-CBC" ou équivalent n'est disponible.

Lorsqu'un client SSH se connecte à un serveur, l'une des premières étapes est de négocier les méthodes utilisées pour le chiffrement. SSH est un protocole flexible et plusieurs méthodes sont supportées pour l'échange de clés, l'authentification du serveur, le chiffrement et l'intégrité des messages. Tout ceci est contrôlé par les options suivantes définies dans le fichier de configuration sshd_config: KexAlgorithms, HostKeyAlgorithms, Ciphers et MACs (respectivement). Des valeurs par défaut sont utilisées si rien n'est spécifié.

Regardons le statut d'un serveur OpenSSH sur un système Ubuntu un peu âgé (18.10 LTS) à l'aide de nmap :

ellendhel@laptop:~$ nmap -p T:22 --script ssh2-enum-algos -sV server.example.net
Starting Nmap 7.70 ( https://nmap.org ) at 2022-06-11 21:42 EDT
Nmap scan report for server.example.net (192.168.36.15)
Host is up (0.046s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh2-enum-algos:
|   kex_algorithms: (10)
|       curve25519-sha256
|       curve25519-sha256@libssh.org
|       ecdh-sha2-nistp256
|       ecdh-sha2-nistp384
|       ecdh-sha2-nistp521
|       diffie-hellman-group-exchange-sha256
|       diffie-hellman-group16-sha512
|       diffie-hellman-group18-sha512
|       diffie-hellman-group14-sha256
|       diffie-hellman-group14-sha1
|   server_host_key_algorithms: (5)
|       ssh-rsa
|       rsa-sha2-512
|       rsa-sha2-256
|       ecdsa-sha2-nistp256
|       ssh-ed25519
|   encryption_algorithms: (6)
|       chacha20-poly1305@openssh.com
|       aes128-ctr
|       aes192-ctr
|       aes256-ctr
|       aes128-gcm@openssh.com
|       aes256-gcm@openssh.com
|   mac_algorithms: (10)
|       umac-64-etm@openssh.com
|       umac-128-etm@openssh.com
|       hmac-sha2-256-etm@openssh.com
|       hmac-sha2-512-etm@openssh.com
|       hmac-sha1-etm@openssh.com
|       umac-64@openssh.com
|       umac-128@openssh.com
|       hmac-sha2-256
|       hmac-sha2-512
|       hmac-sha1
|   compression_algorithms: (2)
|       none
|_      zlib@openssh.com
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 0.83 seconds
ellendhel@laptop:~$

Le nombre indiqué entre parenthèses est le nombre d'options activées. On remarquera qu'ils sont tous assez élevés, le but étant de proposer suffisamment de choix pour être accessible par une grande variété de clients.

Plusieurs de ces options sont ne sont plus considérées comme étant robuste à l'heure actuelle, il vous faut donc reconfigurer OpenSSH. Là où les choses se compliquent, si vous reconfigurez un serveur distant, une nouvelle configuration invalide vous coupera l'accès dont vous avez besoin.

La solution est d'instancier un second service SSH, sur un port différent, appliquant la configuration que vous voulez tester :

sudo /usr/sbin/sshd -p 2020 -Dd -f sshd_config-HARDENED

Explications : l'option "-p" vous permet de déclarer le port TCP à utiliser en remplacement du port 22. Attention, ne pas oublier d'ajuster temporairement les règles du pare-feu de votre machine pour autoriser les connections sur ce port ! Les options "-Dd" permettent de lancer OpenSSH en mode détaché (et non en tant que service, daemon) et avec de le mode de débogage activé, ce qui vous fournira plus de détails. Enfin, l'option "-f" permet de donner le nom du fichier de configuration à valider.

Pour cet article, voici la configuration qui a été appliquée (ajoutée au fichier standard). Ne recopiez pas directement les lignes suivantes, assurez-vous qu'elles correspondent à vos besoins en premier lieu.

HostKey /etc/ssh/ssh_host_ed25519_key
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com

Il est aussi important de noter que l'ordre de chaque option défini celle qui sera utilisée en priorité.

Le script "ssh2-enum-algos" de nmap ne semble malheureusement pas permettre de tester un autre port que TCP/22 ; vous devez donc utiliser un client SSH avec des options complémentaires pour effectuer votre test :

ssh -v server.example.net -p 2020

Parmi toutes les lignes affichées vous devez trouver les nouvelles listes de valeurs pour KexAlgorithms, Ciphers et MACs. Et l'accès distant devrait être fonctionnel ; si ce n'est pas le cas, vérifiez votre configuration et testez à nouveau.

Une fois les validations faites, votre nouvelle configuration pourra remplacer celle par défaut. Redémarrez le service et un test final pourra confirmer le résultat de vos efforts :

ellendhel@laptop:~$ nmap -p T:22 --script ssh2-enum-algos -sV server.example.net
Starting Nmap 7.70 ( https://nmap.org ) at 2022-06-11 16:55 EDT
Nmap scan report for server.example.net (192.168.36.15)
Host is up (0.029s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh2-enum-algos:
|   kex_algorithms: (2)
|       curve25519-sha256@libssh.org
|       diffie-hellman-group-exchange-sha256
|   server_host_key_algorithms: (1)
|       ssh-ed25519
|   encryption_algorithms: (6)
|       chacha20-poly1305@openssh.com
|       aes256-gcm@openssh.com
|       aes128-gcm@openssh.com
|       aes256-ctr
|       aes192-ctr
|       aes128-ctr
|   mac_algorithms: (3)
|       hmac-sha2-512-etm@openssh.com
|       hmac-sha2-256-etm@openssh.com
|       umac-128-etm@openssh.com
|   compression_algorithms: (2)
|       none
|_      zlib@openssh.com
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 0.58 seconds
ellendhel@laptop:~$

Les choix pour votre nouvelle configuration dépendront beaucoup de votre environnement : quel type d'utilisateurs accèdent à votre système ? Seront-ils capable d'utiliser des options supplémentaires si nécessaire ? Avez-vous des tâches automatisées qui demanderont d'être adaptées ? En cas de changement de clé d'hôte (comme c'est le cas ici, forçant uniquement l'utilisation de EdDSA) l'acceptation d'une nouvelle empreinte (key fingerprint) pourra bloquer un accès existant.

Prévoyez d'annoncer ce changement à l'avance et gardez une solution de retour en arrière si nécessaire (il suffit de revenir au fichier de configuration précédent). Et si votre organisation requiert que toutes les vulnérabilités reportées soient traitées, n'hésitez pas à expliquer les besoins de compatibilité si besoin est. Dans certain cas, cela peut justifier une exception.

Quelques liens additionnels sur le sujet :

publié le 11 juin 2022

lien direct

LinuxDe l'importance des tests

Suite à mon précédent article j'ai commencé à utiliser le script "create-duplicate-list" sur une large quantité de fichiers, dont je savais que plusieurs copies surnuméraires existaient.

Le nombre de fichiers étant conséquent (147437), certains étant volumineux et le tout stocké sur un disque mécanique je savais qu'il faudrait du temps pour générer une liste. Néanmoins, après plusieurs utilisations, le temps d'exécution me paraissait tout de même élevé, malgré les améliorations apportéees.

En examinant de plus près le code et les fichiers temporaires un constat s'est imposé : le nouveau script n'était pas plus efficace que l'ancien. Une simple étape de substitution manquait. Le code manquant avait bien été préparé mais, pour une raison obscure, n'avait pas été intégré au script...

Résultat du script originel :

[ 2020-04-11 14:29:01 ] Listing file sizes...
[ 2020-04-11 14:29:18 ] Computing MD5 checksums...
[ 2020-04-11 15:31:51 ] Done.
[ 2020-04-11 15:31:52 ] Sorting the list...
[ 2020-04-11 15:31:52 ] Done.
[ 2020-04-11 15:31:52 ] Listing duplicates...
[ 2020-04-11 15:31:52 ] Done.
[ 2020-04-11 15:31:52 ] Generating the CSV file...
[ 2020-04-11 15:31:56 ] Done.

Soit un délai d'exécution d'environ une heure.

Résultats du script après correction (et un arrêt complet du système pour éviter des phénomènes de cache) :

[ 2020-04-11 16:05:00 ] Listing file sizes...
[ 2020-04-11 16:05:18 ] Computing MD5 checksums...
[ 2020-04-11 16:18:26 ] Done.
[ 2020-04-11 16:18:26 ] Sorting the list...
[ 2020-04-11 16:18:26 ] Done.
[ 2020-04-11 16:18:26 ] Listing duplicates...
[ 2020-04-11 16:18:26 ] Done.
[ 2020-04-11 16:18:26 ] Generating the CSV file...
[ 2020-04-11 16:18:31 ] Done.

Ce qui nous donne un délai d'exécution d'environ... 13 minutes ! Et un résultat identique.

En observant les fichiers temporaires produits par le script, il est possible de voir que la version originelle liste autant de fichiers à traiter que ceux présent sur le disque. La version corrigée n'en liste que 87945. Ce qui était bien le but de l'optimisation recherchée.

Ce qui m'amène au titre de cet article : tester son code est essentiel. Vous devez bien évidemment vérifier la logique et la syntaxe, mais l'environnement et les données que vous utilisez sont tout aussi importants.

Travailler sur un jeu de données limitées permet de conduire des tests rapidement, mais il faut veiller à ce que ce jeu de données soit aussi proche de la réalité que possible (variété de types de fichiers, de tailles, arborescence, ...). Des tests en conditions trop homogènes conduiront à la découverte de bugs une fois votre application déployée en production.

publié le 11 avril 2020

lien direct

LinuxScript "create-duplicate-list" - version 2

Il y a environ un an, la version initiale du script "create-duplicate-list" était ajoutée à mon dépôt GitLab. Ce script répond à un besoin assez simple : "comment lister les fichiers identiques dans une arborescence de fichiers ?".

L'approche utilisée pour résoudre ce problème était simpliste : pour chaque fichier présent, calculer la somme de contrôle MD5. Une fois tous les fichiers identifiés, lister ceux ayant une somme de contrôle identique. La décision de supprimer une des copies surnuméraire demeure celle de l'utilisateur, le script n'ayant aucune notion de contexte pour juger laquelle devant être éliminée.

Le problème de ce script est que face à de nombreux fichiers, son exécution est lente ; tous sont examinés, quand bien même leur caractéristiques les rendent uniques (à l'opposé, deux fichiers identiques portant des noms différents seront détectés).

Avec un peu de recul, il est assez évident de procéder à une optimisation : seuls les fichiers de taille identique doivent être considérés. Cette deuxième mouture commence donc par lister tous les fichiers avec leur taille. Puis en se basant sur les résultats, le calcul des sommes de contrôle ne sera faite que pour les doublons.

Le gain n'est pas forcément très significatif ; beaucoup de fichiers peuvent avoir des tailles similaires (quantités de photos prises par un même appareil ont une taille moyenne proche). Tout dépendra du type de données sur lesquelles vous travaillez.

Le travail pour cette nouvelle version à été intéressant à plus d'un titre ; ajouter une étape préliminaire semblait d'emblée très simple mais plusieurs options et paramètres en général ignorés étaient nécessaire pour utiliser les traditionnels find, uniq ou sed.

Oui, il est possible d'utiliser uniq pour ne traiter que certain champs sur une ligne, mais non, vous ne pouvez pas choisir quel est le caractère utilisé pour les séparer. Vous devez au préalable procéder à des substitutions, que vous annulerez juste après.

Oui, il est possible d'utiliser un autre caractère que slash pour une commande avec sed, cela est même nécessaire si la valeur que vous ajoutez est un nom de répertoire.

Comme toujours la lecture des pages de manuel, plus des recherches vous guidant vers différents coins du web sont des sources qui vous apporteront frustrations et surprises, mais qui au final vous permettent de créer des outils plus élaborés.

publié le 9 avril 2020

lien direct