TL;DR. Dans cet article, nous explorons les schémas de sécurité (hardening schemes) qui fonctionnent par défaut dans cinq distributions populaires de Linux. Pour chacune, nous avons pris la configuration du noyau par défaut, chargé tous les paquets et analysé les schémas de protection dans les fichiers binaires imbriqués. Les distributions examinées sont OpenSUSE 12.4, Debian 9, CentOS, RHEL 6.10 et 7, ainsi qu'Ubuntu 14.04, 12.04 et 18.04 LTS.
Les résultats confirment que même les schémas de base, tels que les canaris de pile et le code indépendant de la position, ne sont pas encore utilisés par tous. La situation est encore pire pour les compilateurs en ce qui concerne la protection contre les vulnérabilités telles que le clash de pile (stack clash), qui a été au centre des préoccupations en janvier après la publication . Mais tout n'est pas désespéré. Une partie significative des binaires dispose de méthodes de protection de base, et leur nombre augmente à chaque version.
La vérification a montré que le plus grand nombre de méthodes de protection est mis en œuvre dans Ubuntu 18.04 au niveau du système d'exploitation et des applications, suivi par Debian 9. D'autre part, OpenSUSE 12.4, CentOS 7 et RHEL 7 disposent également de schémas de protection basiques, et la protection contre le clash de pile est appliquée encore plus largement avec un ensemble de paquets par défaut beaucoup plus dense.
Introduction
Il est difficile d'assurer une haute qualité logicielle. Malgré un grand nombre d'outils avancés pour l'analyse statique du code et l'analyse dynamique à l'exécution, ainsi qu'un progrès significatif dans le développement de compilateurs et de langages de programmation, les logiciels modernes souffrent encore de vulnérabilités qui sont constamment exploitées par des attaquants. La situation est encore plus critique dans les écosystèmes comprenant du code obsolète. Dans de tels cas, nous ne sommes pas seulement confrontés au problème éternel de la recherche de potentielles erreurs exploitables, mais nous sommes également limités par des contraintes rigides de rétrocompatibilité qui exigent souvent de conserver un code limité, voire pire, vulnérable ou bogué.
C'est ici que les méthodes de protection ou de durcissement des programmes (hardening) entrent en jeu. Certains types d'erreurs sont inévitables, mais nous pouvons compliquer la tâche des attaquants et partiellement résoudre le problème en empêchant ou en entravant. d'exploitation ces erreurs. Une telle protection est utilisée dans tous les systèmes d'exploitation modernes, mais les méthodes varient considérablement en termes de complexité, d'efficacité et de performance : des canaris de pile (stack canaries) et des protections complètes. et Dans cet article, nous examinerons les méthodes de protection appliquées dans les distributions Linux les plus populaires dans leur configuration par défaut, ainsi que les propriétés des binaires distribués via les systèmes de gestion de paquets de chaque distribution.
CVE et sécurité
Nous avons tous vu des articles avec des titres tels que « Les applications les plus vulnérables de l'année » ou « Les systèmes d'exploitation les plus vulnérables ». Ces articles présentent généralement des statistiques sur le nombre total d'enregistrements de vulnérabilités de type , obtenues à partir de à partir de et d'autres sources. Par la suite, ces applications ou systèmes d'exploitation sont classés en fonction du nombre de CVE. Malheureusement, bien que les CVE soient très utiles pour le suivi des problèmes et pour informer les fournisseurs et les utilisateurs, elles ne disent pas grand-chose sur la réelle sécurité des logiciels.
À titre d'exemple, examinons le nombre total de CVE au cours des quatre dernières années pour le noyau Linux et les cinq distributions serveur les plus populaires, à savoir Ubuntu, Debian, Red Hat Enterprise Linux et OpenSUSE.

Fig. 1
Que nous dit ce graphique ? Un plus grand nombre de CVE signifie-t-il qu'une distribution est plus vulnérable qu'une autre ? La réponse est non. Par exemple, dans cet article, vous verrez que Debian a mis en œuvre des mécanismes de protection plus stricts par rapport, disons, à OpenSUSE ou RedHat Linux, et pourtant, Debian a plus de CVE. Cependant, cela ne signifie pas nécessairement une sécurité affaiblie : même la présence de CVE ne dit pas si la vulnérabilité est exploitable.Les scores de gravité donnent une idée de la probabilité d'exploitation d'une vulnérabilité, mais en fin de compte, l'exploitabilité dépend en grande partie des protections présentes dans les systèmes concernés, ainsi que des ressources et des capacités des attaquants. De plus, l'absence de rapports CVE ne dit rien sur d'autres vulnérabilités non enregistrées ou inconnues. non enregistrés ou inconnus Les vulnérabilités. La différence dans les CVE peut s'expliquer non par la qualité des logiciels, mais par d'autres facteurs, y compris les ressources allouées aux tests ou la taille de la base d'utilisateurs. Dans notre exemple, un plus grand nombre de CVE pour Debian peut simplement indiquer que Debian fournit plus de paquets logiciels.
Bien sûr, le système CVE fournit des informations utiles qui permettent de créer des protections appropriées. Plus nous comprenons les causes des défaillances des programmes, plus il est facile d'identifier les moyens potentiels d'exploitation et de développer des mécanismes correspondants. de détection et de réponse. La figure 2 montre les catégories de vulnérabilités pour toutes les distributions au cours des quatre dernières années (). On voit tout de suite que la majorité des CVE se classent dans les catégories suivantes : déni de service (DoS), exécution de code, débordement, corruption de mémoire, fuite (exfiltration) d'informations et élévation de privilèges. Bien que de nombreuses CVE soient comptées plusieurs fois dans différentes catégories, les mêmes problèmes persistent d'année en année. Dans la suite de l'article, nous évaluerons l'utilisation de différents schémas de protection pour prévenir l'exploitation des vulnérabilités mentionnées.

Figure 2
Objectifs
Dans cet article, nous avons l'intention de répondre aux questions suivantes :
- Quelle est la sécurité des différentes distributions Linux ? Quels mécanismes de protection existent dans le noyau et les applications de l'espace utilisateur ?
- Comment l'adoption des mécanismes de protection a-t-elle évolué au fil du temps pour différentes distributions ?
- Quelles sont les dépendances moyennes des paquets et des bibliothèques de chaque distribution ?
- Quelles protections sont mises en œuvre pour chaque binaire ?
Choix des distributions
Il s'avère qu'il est difficile de trouver des statistiques précises sur les installations de distributions, car dans la plupart des cas, le nombre de téléchargements n'indique pas le nombre d'installations réelles. Néanmoins, les variantes de Unix représentent la majorité des systèmes serveurs (69,2 % sur les serveurs web, selon W3techs et d'autres sources), et leur part ne cesse de croître. Ainsi, pour notre étude, nous nous sommes concentrés sur les distributions disponibles « prêtes à l'emploi » sur la plateforme . En particulier, nous avons sélectionné les systèmes d'exploitation suivants :
Distribution/version
Le noyau
Build
OpenSUSE 12.4
4.12.14-95.3-default
#1 SMP Wed Dec 5 06:00:48 UTC 2018 (63a8d29)
Debian 9 (stretch)
4.9.0-8-amd64
#1 SMP Debian 4.9.130-2 (2018-10-27)
CentOS 6.10
2.6.32-754.10.1.el6.x86_64
#1 SMP Tue Jan 15 17:07:28 UTC 2019
CentOS 7
3.10.0-957.5.1.el7.x86_64
#1 SMP Fri Feb 1 14:54:57 UTC 2019
Red Hat Enterprise Linux Server 6.10 (Santiago)
2.6.32-754.9.1.el6.x86_64
#1 SMP Wed Nov 21 15:08:21 EST 2018
Red Hat Enterprise Linux Server 7.6 (Maipo)
3.10.0-957.1.3.el7.x86_64
#1 SMP Thu Nov 15 17:36:42 UTC 2018
Ubuntu 14.04 (Trusty Tahr)
4.4.0–140-generic
#166~14.04.1-Ubuntu SMP Sat Nov 17 01:52:43 UTC 20…
Ubuntu 16.04 (Xenial Xerus)
4.15.0–1026-gcp
#27~16.04.1-Ubuntu SMP Fri Dec 7 09:59:47 UTC 2018
Ubuntu 18.04 (Bionic Beaver)
4.15.0–1026-gcp
#27-Ubuntu SMP Thu Dec 6 18:27:01 UTC 2018
Tableau 1
Analyse
Nous examinerons la configuration du noyau par défaut, ainsi que les propriétés des paquets disponibles via le gestionnaire de paquets de chaque distribution dès l'installation. Ainsi, nous ne considérerons que les paquets des miroirs par défaut de chaque distribution, en ignorant les paquets des dépôts instables (comme les miroirs 'testing' dans Debian) et les paquets tiers (par exemple, les paquets Nvidia des miroirs standards). De plus, nous n'examinerons pas les compilations personnalisées du noyau ou les configurations renforcées.
Analyse de la configuration du noyau
Nous avons appliqué un script d'analyse basé sur . Nous examinons les paramètres de sécurité par défaut des distributions nommées et les comparons à la liste de (KSPP). Pour chaque paramètre de configuration, le tableau 2 décrit le paramètre souhaité : une coche est mise pour les distributions qui respectent les recommandations de KSSP (explication des termes cf. ; dans des articles futurs, nous expliquerons comment de nombreuses méthodes de protection sont apparues et comment contourner le système en leur absence).

Dans l'ensemble, les nouveaux noyaux ont des réglages par défaut plus stricts. Par exemple, CentOS 6.10 et RHEL 6.10 avec le noyau 2.6.32 manquent de la plupart des fonctionnalités critiques mises en œuvre dans les nouveaux noyaux, telles que , des permissions RWX strictes, la randomisation des adresses ou la protection copy2usr. Il convient de noter que de nombreuses options de configuration figurant dans le tableau sont absentes dans les versions plus anciennes du noyau et ne sont pas applicables en réalité - cela est tout de même indiqué dans le tableau comme absence de protection adéquate. De même, si un paramètre de configuration est absent dans cette version, mais que ce paramètre doit être désactivé pour des raisons de sécurité, cela est considéré comme une configuration raisonnable.
Un autre point à considérer lors de l'interprétation des résultats : certaines configurations du noyau qui augmentent la surface d'attaque peuvent également être utilisées à des fins de sécurité. Des exemples de cela incluent uprobes et kprobes, les modules du noyau et BPF/eBPF. Notre recommandation est d'utiliser ces mécanismes mentionnés ci-dessus pour garantir une réelle protection, car leur utilisation n'est pas triviale et leur exploitation suppose que des agents malveillants sont déjà ancrés dans le système. Mais si ces options sont activées, l'administrateur système doit surveiller activement les abus.
En poursuivant l'examen des enregistrements du tableau 2, nous constatons que les noyaux modernes offrent plusieurs options pour se défendre contre l'exploitation de vulnérabilités telles que les fuites d'informations et le débordement de pile/monticule. Cependant, nous constatons que même les distributions les plus récentes et populaires n'ont pas encore mis en œuvre de protections plus complexes (par exemple, avec des correctifs ) ou de protections modernes contre les attaques de réutilisation de code (par exemple, ). Pire encore, même ces outils de protection plus avancés ne protègent pas contre l'ensemble du spectre des attaques. Ainsi, il est crucial que les administrateurs système complètent des configurations judicieuses par des solutions offrant détection et prévention des exploits en temps réel.
Analyse des applications
Il n'est pas surprenant que différentes distributions aient des caractéristiques variées en matière de paquets, d'options de compilation, de dépendances de bibliothèques, etc. Des différences existent même pour apparentées et des paquets avec peu de dépendances (par exemple, coreutils dans Ubuntu ou Debian). Pour évaluer ces différences, nous avons téléchargé tous les paquets disponibles, extrait leur contenu et analysé les fichiers binaires et leurs dépendances. Pour chaque paquet, nous avons tracé d'autres paquets dont il dépend, et pour chaque binaire, nous avons suivi ses dépendances. Dans cette section, nous allons résumer nos conclusions.
Distributions
Au total, nous avons téléchargé 361 556 paquets pour toutes les distributions, extrayant uniquement les paquets à partir des miroirs par défaut. Nous avons ignoré les paquets sans fichiers exécutables ELF, tels que les codes sources, les polices, etc. Après filtrage, il ne reste que 129 569 paquets contenant au total 584 457 fichiers binaires. La répartition des paquets et des fichiers par distribution est présentée à la figure 3.

Fig. 3
On peut noter que plus la distribution est moderne, plus elle contient de paquets et de fichiers binaires, ce qui est logique. En revanche, les paquets Ubuntu et Debian incluent beaucoup plus de fichiers binaires (tant exécutables que modules et bibliothèques dynamiques) que CentOS, SUSE et RHEL, ce qui peut potentiellement augmenter la surface d'attaque d'Ubuntu et de Debian (il faut observer que les chiffres reflètent tous les binaires de toutes les versions des paquets, c'est-à-dire que certains fichiers sont analysés plusieurs fois). Ceci est particulièrement important lorsqu'on considère les dépendances entre paquets. Ainsi, une vulnérabilité dans le binaire d'un paquet peut affecter de nombreuses parties de l'écosystème, tout comme une bibliothèque vulnérable peut impacter tous les fichiers binaires qui l'importent. Prenons comme point de départ la répartition du nombre de dépendances par paquet dans différents systèmes d'exploitation :
Fig. 4
Dans presque toutes les distributions, 60 % des paquets ont au moins 10 dépendances. De plus, certains paquets ont un nombre de dépendances considérablement plus élevé (plus de 100). Il en va de même pour les dépendances inverses des paquets : comme prévu, plusieurs paquets sont utilisés par de nombreux autres paquets dans la distribution, rendant les vulnérabilités de ces rares élus très risquées. À titre d'exemple, dans le tableau suivant, nous listons 20 paquets avec le maximum de dépendances inverses dans SLES, Centos 7, Debian 9 et Ubuntu 18.04 (chaque cellule indique le paquet et le nombre de dépendances inverses).

Tableau 3
Fait intéressant. Bien que tous les systèmes d'exploitation analysés soient construits pour l'architecture x86_64, et que la majorité des paquets soient définis pour l'architecture x86_64 et x86, les paquets contiennent souvent des fichiers binaires pour d'autres architectures, comme le montre la figure 5.

Fig. 5
Dans la section suivante, nous approfondirons les caractéristiques des binaires analysés.
Statistiques de protection des fichiers binaires
En tant que minimum absolu, il est nécessaire d'étudier un ensemble de protections de base pour les fichiers binaires existants. Plusieurs distributions Linux sont livrées avec des scripts qui effectuent de telles vérifications. Par exemple, sur Debian/Ubuntu, il existe un tel script. Voici un exemple de son fonctionnement :
$ hardening-check $(which docker)
/usr/bin/docker:
Exécutable Indépendant de Position : oui
Protection de la Pile : oui
Fonctions Source Fortifiées : non, seules des fonctions non protégées trouvées !
Relocalisations en Lecture Seule : oui
Liaison Immédiate : ouiLe script vérifie cinq :
- Exécutable Indépendant de Position (PIE) : indique si la section texte du programme peut être déplacée en mémoire pour obtenir de la randomisation si l'ASLR est activé dans le noyau.
- Protection de la Pile : les canaris de pile sont-ils activés pour se protéger contre les attaques de débordement de pile.
- Fortification de la Source : les fonctions non sécurisées (par exemple, strcpy) sont-elles remplacées par leurs équivalents plus sûrs, et les appels vérifiés à l'exécution — par leurs équivalents non vérifiés (par exemple, memcpy au lieu de __memcpy_chk).
- Relocalisations en Lecture Seule (RELRO) : les entrées de la table de relocalisation sont-elles marquées comme « uniquement en lecture », si elles ont fonctionné avant le début de l'exécution.
- Liaison Immédiate : le chargeur d'exécution est-il autorisé à résoudre toutes les relocalisations avant le début de l'exécution du programme (ce qui équivaut à un RELRO complet).
Les mécanismes ci-dessus sont-ils suffisants ? Malheureusement, non. Il existe des moyens de contourner toutes les protections ci-dessus, mais plus la protection est stricte, plus la barre est haute pour l'attaquant. Par exemple, sont plus difficiles à appliquer lorsque le PIE et la liaison immédiate sont en vigueur. De même, un ASLR complet nécessite un travail supplémentaire pour créer un exploit fonctionnel. Cependant, des attaquants raffinés sont déjà prêts à faire face à de telles protections : leur absence accélère en réalité le piratage. Il est donc crucial que ces mesures soient considérées comme un minimum.
Nous souhaitions étudier combien de fichiers binaires dans les distributions examinées sont protégés par ceux-ci, ainsi que par trois autres méthodes :
- Le bit Non Exécutif () empêche l'exécution dans toute zone qui ne devrait pas être exécutable, par exemple dans la pile, etc.
- indique le chemin d'exécution utilisé par le chargeur dynamique pour trouver les bibliothèques appropriées. Le premier est obligatoire pour tout système moderne : son absence permet aux attaquants d'écrire des charges utiles dans la mémoire et de les exécuter telles quelles. Pour le second, des configurations incorrectes des chemins d'exécution aident à l'introduction de code non fiable, ce qui peut conduire à une série de problèmes (par exemple, , ainsi que ).
- La protection contre la collision de piles offre une protection contre les attaques qui poussent la pile à se superposer à d'autres zones de mémoire (par exemple, à la pile). Étant donné les exploits récents abusant , nous avons jugé approprié d'inclure ce mécanisme dans notre ensemble de données.
Ainsi, sans plus de cérémonies, passons aux chiffres. Les tableaux 4 et 5 contiennent un extrait de l'analyse des fichiers exécutables et des bibliothèques de diverses distributions, respectivement.
- Comme on peut le constater, la protection NX est mise en œuvre partout, à de rares exceptions près. En particulier, on peut noter une utilisation légèrement inférieure dans les distributions Ubuntu et Debian par rapport à CentOS, RHEL et OpenSUSE.
- Les canaris de pile sont souvent absents, surtout dans les distributions avec des noyaux plus anciens. Quelques progrès ont été réalisés dans les dernières distributions de CentOS, RHEL, Debian et Ubuntu.
- À l'exception de Debian et Ubuntu 18.04, la plupart des distributions présentent un mauvais soutien de PIE.
- La protection contre les collisions de piles est faiblement implémentée dans OpenSUSE, CentOS 7 et RHEL 7 et est pratiquement absente chez les autres.
- Toutes les distributions avec des noyaux modernes ont un certain soutien de RELRO, avec Ubuntu 18.04 en tête et Debian à la deuxième place.
Comme mentionné précédemment, les métriques dans ce tableau sont des moyennes sur toutes les versions du fichier binaire. Si l'on ne regarde que les dernières versions des fichiers, les chiffres seront différents (par exemple, voir ). De plus, la plupart des distributions, lorsqu'elles comptent des statistiques, ne vérifient la protection que de quelques fonctions dans le code binaire, alors que notre analyse indique le pourcentage réel de fonctions renforcées. Ainsi, si 5 des 50 fonctions sont protégées dans le binaire, nous lui attribuerons une note de 0,1, correspondant à 10 % de fonctions protégées.

Tableau 4. Caractéristiques de protection pour les fichiers exécutables, illustrées à la figure 3 (mise en œuvre des fonctions correspondantes en pourcentage du nombre total de fichiers exécutables)

Tableau 5. Caractéristiques de sécurité des bibliothèques présentées à la fig. 3 (implémentation des fonctions correspondantes en pourcentage du nombre total de bibliothèques)
Donc, y a-t-il des progrès ? Il y en a définitivement : cela se voit dans les statistiques de certaines distributions (par exemple, ), ainsi que dans les tableaux ci-dessus. À titre d'exemple, la fig. 6 montre l'implémentation des mécanismes de protection dans trois distributions Ubuntu LTS consécutives (nous avons omis les statistiques de protection contre les débordements de pile). Nous remarquons que d'une version à l'autre, de plus en plus de fichiers prennent en charge les canaris de pile, et de plus en plus de fichiers binaires sont fournis avec une protection RELRO complète.
Fig. 6
Malheureusement, un certain nombre de fichiers exécutables dans différentes distributions n'ont toujours aucune des protections mentionnées ci-dessus. Par exemple, en regardant Ubuntu 18.04, on peut noter le binaire ngetty (remplaçant de getty), ainsi que les shells mksh et lksh, l'interpréteur picolisp, les paquets nvidia-cuda-toolkit (un paquet populaire pour les applications accélérées par GPU, telles que les frameworks d'apprentissage automatique) et klibc-utils. De même, le binaire mandos-client (outil administratif permettant de redémarrer automatiquement les machines avec des systèmes de fichiers chiffrés), ainsi que le rsh-redone-client (réimplémentation de rsh et rlogin) sont fournis sans protection NX, bien qu'ils aient des droits SUID :(. De plus, plusieurs binaires avec SUID n'ont pas de protection de base, comme les canaris de pile (par exemple, le fichier binaire Xorg.wrap du paquet Xorg).
Résumé et observations finales
Dans cet article, nous avons mis en avant plusieurs caractéristiques de sécurité des distributions Linux modernes. L'analyse a montré que la dernière version d'Ubuntu LTS (18.04) offre en moyenne la meilleure protection au niveau du système d'exploitation et des applications parmi les distributions avec des noyaux relativement récents, telles qu'Ubuntu 14.04, 12.04 et Debian 9. Cependant, les distributions considérées comme CentOS, RHEL et OpenSUSE dans notre ensemble de données livrent par défaut un ensemble de paquets plus robuste, et dans les dernières versions (CentOS et RHEL) affichent un pourcentage plus élevé de mise en œuvre de la protection contre le débordement de pile, par rapport à leurs concurrents basés sur Debian (Debian et Ubuntu). En comparant les versions CentOS et RedHat, nous observons d'importantes améliorations dans le déploiement des canaris de pile et du RELRO entre les versions 6 et 7, mais en moyenne, CentOS offre plus de fonctionnalités que RHEL. Dans l'ensemble, toutes les distributions devraient accorder une attention particulière à la protection PIE, qui, à l'exception de Debian 9 et Ubuntu 18.04, n'est mise en œuvre que dans moins de 10 % des fichiers binaires de notre ensemble de données.
Enfin, il convient de noter : bien que nous ayons mené cette recherche manuellement, il existe de nombreux outils de sécurité (par exemple, , , ), qui effectuent des analyses et aident à éviter les configurations non sécurisées. Malheureusement, même une forte protection dans des configurations raisonnables ne garantit pas l'absence d'exploits. C'est pourquoi nous croyons fermement qu'il est essentiel d'assurer , en se concentrant sur les modèles d'exploitation et en les empêchant.
Source : habr.com
