Rust de Mozilla Research est le type de langage de programmation auquel ceux qui écrivent du code pour des systèmes d’entrée/sortie de base (BIOS), des chargeurs d’amorce, des systèmes d’exploitation, etc. portent un intérêt. De façon graduelle, Microsoft migre vers ce dernier au détriment d’autres langages que l’entreprise juge moins outillés pour la mise sur pied d’applications dites système. Motif : Rust offre de meilleures garanties en matière de sécurisation des accès mémoire des logiciels.
« Les problèmes de gestion de la mémoire sont exploités depuis des décennies et sont encore trop courants aujourd'hui. Nous devons utiliser de façon systématique des langages sécurisés pour la mémoire et d'autres protections lors du développement de logiciels afin d'éliminer ces faiblesses des cyberacteurs malveillants », déclare Neal Ziring, directeur technique de la cybersécurité de la NSA.
Une publication de la NSA permet de faire le tour sur ce problème de la sécurité de la mémoire
La façon dont un programme logiciel gère la mémoire est essentielle pour prévenir de nombreuses vulnérabilités et garantir la robustesse d'un programme. L'exploitation d'une gestion de la mémoire médiocre ou négligente peut permettre à un cyberacteur malveillant d'accomplir des actes néfastes, tels que planter le programme à volonté ou modifier les instructions du programme en cours d'exécution pour faire ce que l'acteur désire. Même des problèmes inexploitables avec la gestion de la mémoire peuvent entraîner des résultats de programme incorrects, une dégradation des performances du programme au fil du temps ou des plantages de programme apparemment aléatoires.
La sécurité de la mémoire est une vaste catégorie de problèmes liés à la façon dont un programme gère la mémoire. Un problème courant est le « débordement de tampon », où les données sont accessibles en dehors des limites d'un tableau. D'autres problèmes courants concernent l'allocation de mémoire. Les langages peuvent allouer de nouveaux emplacements de mémoire pendant l'exécution d'un programme, puis désallouer la mémoire, également appelée libération ou libération de la mémoire, plus tard lorsque la mémoire n'est plus nécessaire. Mais si cela n'est pas fait avec soin par le développeur, de la nouvelle mémoire peut être allouée encore et encore au fur et à mesure que le programme s'exécute. Par conséquent, la mémoire n'est pas toujours libérée lorsqu'elle n'est plus nécessaire, ce qui entraîne une fuite de mémoire qui pourrait entraîner le programme à manquer de mémoire disponible.
En raison d'erreurs logiques, les programmes peuvent également tenter d'utiliser la mémoire qui a été libérée, ou même de libérer de la mémoire qui a déjà été libérée. Un autre problème peut survenir lorsque les langages autorisent l'utilisation d'une variable qui n'a pas été initialisée, ce qui fait que la variable utilise la valeur précédemment définie à cet emplacement en mémoire. Enfin, un autre problème difficile est appelé une condition de concurrence. Ce problème peut se produire lorsque les résultats d'un programme dépendent de l'ordre de fonctionnement de deux parties du programme accédant aux mêmes données. Tous ces problèmes de mémoire sont des occurrences beaucoup trop courantes.
En exploitant ces types de problèmes de mémoire, les acteurs malveillants, qui ne sont pas liés par les attentes normales d'utilisation du logiciel, peuvent découvrir qu'ils peuvent entrer des entrées inhabituelles dans le programme, provoquant l'accès, l'écriture, l'allocation ou la désallocation de la mémoire de manière inattendue. Dans certains cas, un acteur malveillant peut exploiter ces erreurs de gestion de la mémoire pour accéder à des informations sensibles, exécuter du code non autorisé ou provoquer d'autres impacts négatifs. Puisqu'il peut falloir beaucoup d'expérimentation avec des entrées inhabituelles pour en trouver une qui provoque une réponse inattendue, les acteurs peuvent utiliser une technique appelée "fuzzing" pour créer de manière aléatoire ou intelligente une multitude de valeurs d'entrée dans le programme jusqu'à ce qu'on en trouve une qui provoque le plantage du programme.
Les progrès des outils et des techniques de fuzzing ont facilité la recherche d'entrées problématiques pour les acteurs malveillants ces dernières années. Une fois qu'un acteur découvre qu'il peut faire planter le programme avec une entrée particulière, il examine le code et travaille pour déterminer ce qu'une entrée spécialement conçue pourrait faire. Dans le pire des cas, une telle entrée pourrait permettre à l'acteur de prendre le contrôle du système sur lequel le programme s'exécute.
C#, Go, Java, Ruby, Rust et Swift font partie des langages pour une gestion sécurisée de la mémoire mais Rust est de plus en plus mis en avant par les géants technologiques
L'utilisation d'un langage sécurisé pour la mémoire peut aider à empêcher les programmeurs d'introduire certains types de problèmes liés à la mémoire. La mémoire est gérée automatiquement dans le cadre du langage informatique ; il ne repose pas sur l'ajout de code par le programmeur pour implémenter des protections de mémoire. Le langage institue des protections automatiques en utilisant une combinaison de vérifications au moment de la compilation et de l'exécution. Ces fonctionnalités inhérentes au langage protègent le programmeur contre l'introduction involontaire d'erreurs de gestion de la mémoire. C#, Go, Java, Ruby, Rust et Swift sont des exemples de langage sécurisé pour la mémoire.
Même avec un langage sécurisé pour la mémoire, la gestion de la mémoire n'est pas entièrement sécurisée pour la mémoire. La plupart des langages de mémoire sécurisés reconnaissent que les logiciels doivent parfois exécuter une fonction de gestion de mémoire non sécurisée pour accomplir certaines tâches. En conséquence, des classes ou des fonctions sont disponibles qui sont reconnues comme non sécurisées pour la mémoire et permettent au développeur d'effectuer une tâche de gestion de la mémoire potentiellement dangereuse. Certains langages exigent que tout ce qui n'est pas sûr en mémoire soit explicitement annoté comme tel pour que le développeur et tous les réviseurs du programme sachent qu'il n'est pas sûr. Les langages sécurisés pour la mémoire peuvent également utiliser des bibliothèques écrites dans des langages non sécurisés pour la mémoire et peuvent donc contenir des fonctionnalités de mémoire non sécurisées. Bien que ces façons d'inclure la mémoire ne soient pas sûres et subvertissent la sécurité inhérente à la mémoire, elles aident à localiser où des problèmes de mémoire pourraient exister, permettant un examen plus approfondi de ces sections de code.
Les langages varient dans leur degré de sécurité de la mémoire institué par des protections et des atténuations inhérentes. Certains langages n'offrent qu'une sécurité de mémoire relativement minimale alors que certains langages sont très stricts et offrent des protections considérables en contrôlant la manière dont la mémoire est allouée, accessible et gérée. Pour les langages avec un niveau extrême de protection inhérente, un travail considérable peut être nécessaire pour obtenir simplement le programme à compiler en raison des vérifications et des protections.
La sécurité de la mémoire peut être coûteuse en matière de performances et de flexibilité. La plupart des langages mémoire sécurisés nécessitent une sorte de récupération de place pour récupérer la mémoire qui a été allouée, mais qui n'est plus nécessaire au programme. Il existe également une surcharge de performances considérable associée à la vérification des limites de chaque accès à la baie qui pourrait potentiellement se trouver en dehors de la baie.
Alternativement, un impact similaire sur les performances peut exister dans un langage non sécurisé en mémoire en raison des vérifications qu'un développeur ajoute au programme pour effectuer la vérification des limites et d'autres protections de gestion de la mémoire. Les coûts supplémentaires liés à l'utilisation de langages non sécurisés pour la mémoire incluent une corruption de mémoire difficile à diagnostiquer et des plantages occasionnels des programmes ainsi que de potentielles exploitations des vulnérabilités d'accès à la mémoire. Il n'est pas anodin de faire passer une infrastructure de développement logiciel mature d'un langage informatique à un autre. Les développeurs qualifiés doivent être formés dans un nouveau langage et il y a un coup d'efficacité lors de l'utilisation d'un nouveau langage.
Les développeurs doivent endurer une courbe d'apprentissage et se frayer un chemin à travers toutes les erreurs de « débutant ». Alors qu'une autre approche consiste à embaucher des développeurs compétents dans un langage sécurisé pour la mémoire, ils auront eux aussi leur propre courbe d'apprentissage pour comprendre la base de code existante et le domaine dans lequel le logiciel fonctionnera.
Source : Offre d’emploi
Et vous ?
Quel état des lieux faites-vous de la sécurité de la mémoire dans nos logiciels actuels ?
Le langage Rust est-il la solution ultime à cette catégorie de problèmes ?
Voir aussi :
La NSA exhorte les organisations à passer à des langages de programmation sécurisés dans la gestion de la mémoire pour éliminer un vecteur d'attaque souvent exploité par les cybercriminels
La NSA et la CISA des États-Unis publient un guide pour renforcer la sécurité des clusters Kubernetes, en vue d'aider les entreprises à rendre leurs infrastructures plus résilientes
« Choisir Rust est opter pour une meilleure sécurisation des logiciels qu'avec le C, mais une efficacité énergétique et une performance d'exécution que seul le C offre », d'après l'équipe AWS