Blog

Pour la cinquième fois, Rust est le langage de programmation le plus apprécié. Est-il notre nouveau sauveur en matière de sécurité ?

Matias Madou, Ph.D.
Publié le 18 juin 2020

Depuis quelques années, il semble que les ingénieurs logiciels du monde entier ne se lassent pas de Rust pour la programmation. Ce langage de programmation relativement nouveau, produit par Mozilla, a conquis le cœur de la communauté Stack Overflow - et, en tant que cohorte très peu encline à souffrir les imbéciles, lorsqu'ils votent quelque chose comme le"langage de programmation le plus aimé" cinq années d'affilée, il est temps que nous nous réveillions tous et que nous en prenions note.

Le langage de programmation Rust incorpore des éléments connus et fonctionnels de langages couramment utilisés, en travaillant selon une philosophie différente qui élimine la complexité, tout en introduisant la performance et la sécurité. Il s'agit d'une courbe d'apprentissage, et de nombreux développeurs n'ont pas beaucoup l'occasion de jouer avec lui - seulement 5,1 % des personnes interrogées sur Stack Overflow l'utilisent couramment. Cela mis à part, on ne peut nier qu'il s'agit d'un langage passionnant, dont la puissance de feu en matière de sécurité est bien supérieure à celle de ses prédécesseurs, comme le C et le C++. L'adoption massive de ce langage va nécessiter quelques changements, tant comportementaux que technologiques... mais pour l'instant, il continue de capter l'attention des développeurs à un niveau théorique.  

... mais attendez, nous devons mettre en lumière une autre chose : il est important de noter que Rust est un langage de programmation qui donne la priorité à la sécurité de la mémoire, et à l'éradication des bogues de sécurité qui sont liés à des problèmes courants de gestion de la mémoire. Ces problèmes sont importants (et causent sans aucun doute plus d'une migraine à l'équipe AppSec), mais ce ne sont pas les seuls défis auxquels nous sommes confrontés en matière de codage sécurisé.

Qu'est-ce que Rust empêche exactement ? Et où sommes-nous encore exposés dans le paysage de la sécurité ? Décortiquons la dernière licorne de la programmation :

La nouvelle frontière de la programmation de systèmes modernes à sécurité mémoire

L'équipe de recherche et de développement de Mozilla a travaillé sur des projets incroyables, et l'investissement dans la programmation Rust en tant que pionnier du logiciel libre ne fait pas exception. Leur vidéo d'introduction donne un aperçu de leur philosophie, avec un thème clé très clair : l'approche actuelle de la sécurité des logiciels est défectueuse, et Rust est conçu pour résoudre une grande partie de ce problème.

Cela semble trop simpliste, d'autant plus que nous sommes confrontés tous les deux jours à d'énormes violations de données - comme la récente et horrible bavure rapportée par EasyJet. Des millions d'enregistrements de données sont fréquemment compromis, presque toujours à cause d'une vulnérabilité d'application web, d'une mauvaise configuration de sécurité ou d'une attaque par hameçonnage, et des langages comme le C++ existent depuis des décennies. Cependant, les développeurs n'ont pas eu le temps de les maîtriser au point de mettre en œuvre les meilleures pratiques de codage sécurisé. Pourquoi en serait-il autrement pour Rust ? De nouveaux langages sont apparus auparavant, et ce n'est pas comme s'ils avaient trouvé un moyen d'éradiquer les vulnérabilités courantes, ou de garantir que tout code écrit est magiquement parfait lorsqu'il est compilé.

Aussi simple que soit le concept, ce sont parfois les réponses simples qui permettent de résoudre les questions complexes. Rust est, dans tous les sens du terme, une révolution dans la programmation de systèmes à mémoire sécurisée qui tient ses promesses à bien des égards... et il sauve certainement le lard des développeurs qui sont susceptibles d'introduire des erreurs qui peuvent causer de gros problèmes si elles ne sont pas détectées. Java, C, C++, et même des langages plus récents comme Kotlin et Golang, restent assez impitoyables pour le développeur non sensibilisé à la sécurité. Avec ces langages, il n'y a pas d'avertissements intégrés, pas de signes particuliers indiquant que la fonction géniale qui vient d'être compilée cache un gremlin de sécurité sous le capot.

Approfondissons donc la question :

Qu'est-ce qui rend Rust si sûr ?

En règle générale, un développeur a pour objectif principal de créer des fonctionnalités, de s'assurer qu'elles sont fonctionnelles et conviviales, voire même d'en faire une source de fierté qu'il serait heureux de faire figurer sur son curriculum vitae. Il est tout à fait normal qu'un développeur crée un excellent logiciel, le livre et passe au projet suivant. À ce stade, les équipes de sécurité recherchent des vulnérabilités et, si elles sont détectées, l'application "finie" peut être renvoyée à l'équipe qui l'a créée pour être corrigée. Le problème peut être simple, ou complètement hors de portée d'un développeur pour y remédier.

Le problème est qu'en surface, les bogues de sécurité n'étaient pas du tout apparents, et si l'analyse, les tests et l'examen manuel du code ne les détectent pas, un pirate peut potentiellement utiliser cette petite fenêtre d'opportunité pour exploiter le bogue.

Aujourd'hui, Rust cherche à empêcher de nombreuses vulnérabilités de se retrouver dans le code : il ne compile tout simplement pas s'il y a des erreurs de syntaxe ou d'autres bogues de sécurité de la mémoire qui causent des problèmes de production tout au long du cycle de vie du logiciel (SDLC). Il s'agit d'une programmation sans risque pour la mémoire, qui garantit qu'il n'y a pas d'accès à une mémoire non valide (quelle que soit la manière dont le logiciel est exécuté). Et comme 70 % de tous les bogues de sécurité résultent de problèmes liés à la gestion de la mémoire, il s'agit là d'un véritable exploit.

La rouille sera signalée et empêchée :

  • Débordement de mémoire tampon
  • Utilisation après la gratuité
  • Doublement libre
  • Déréférencement d'un pointeur nul
  • Utilisation de mémoire non initialisée

Si nous comparons un extrait de code Rust à un code C++, il apparaît clairement que l'un des deux est sûr par défaut. Regardez cet exemple de bug de débordement de mémoire tampon :

#include <iostream></iostream>
#include <string.h></string.h>
int main( void ) {
char a[3] = "12";
char b[4]= "123";
strcpy(a, b); // buffer overflow as len of b is greater than a
std::cout << a << "; " << b << std::endl;
}

Vs.

pub fn main() {
let mut a: [char; 2] = [1, 2];
let b: [char; 3] = [1, 2, 3];
a.copy_from_slice(&b);
}
Comparer un extrait de code Rust

Rust lance un avertissement de sécurité et panique en atteignant la fonction copy_from_slice en cours d'exécution pour éviter un débordement de mémoire tampon, mais pas en cours de compilation.

En ce sens, il s'agit vraiment d'un des langages "à commencer par la gauche". Il mettra en évidence les erreurs et forcera les développeurs à apprendre la bonne façon d'écrire le code afin d'éviter d'introduire des bogues de sécurité liés à la mémoire, de sorte que le respect des délais dépend de l'attention du codeur, de sa capacité à remédier aux problèmes et à rester fidèle à la voie de livraison.

L'approche de ce langage semble simple, mais cela aurait été un exploit incroyable de le faire fonctionner avec une logique aussi puissante, et il le fait. Du point de vue de la sécurité, Rust est un pas de géant... si seulement plus de gens l'utilisaient. Des entreprises comme Dropbox sont les premières à l'utiliser à grande échelle, et cela fait plaisir à voir. Mais il y a d'autres considérations à prendre en compte avant de sauter à la conclusion qu'un problème d'adoption est tout ce qui nous empêche d'avoir un avenir plus sûr.

Le bilan de la rouille.

Il y a quelques petits (ok, grands) problèmes, notamment le fait que la programmation en Rust est plus susceptible d'introduire des bogues qu'il n'y paraît. Elle ne résoudra pas les vulnérabilités du Top 10 de l'OWASP qui continuent à causer des brèches, des retards et une culture générale de techniques de codage peu sûres. Il existe également une dynamique entre l'ange et le diable, ou, comme on l'appelle plus communément : Safe Rust vs. Unsafe Rust.

Comme l'explique la documentation officielle, Safe Rust est la "vraie" forme de Rust, et Unsafe Rust inclut des fonctions qui sont considérées comme "définitivement non sûres", bien qu'elles soient parfois nécessaires - par exemple si l'intégration avec quelque chose dans un autre langage est requise. Cependant, même avec Unsafe Rust, la liste des fonctionnalités supplémentaires reste limitée. En Rust non sécurisé, il est possible d'effectuer les opérations suivantes à l'intérieur de blocs non sécurisés :

  • Déréférencer les pointeurs bruts
  • Appeler des fonctions non sûres (y compris les fonctions C, les fonctions intrinsèques du compilateur et l'allocateur brut).
  • Mettre en œuvre des caractéristiques non sûres
  • Mutation de la statique
  • Accéder aux champs des syndicats.

Même dans un mode dit "unsafe", l'un des superpouvoirs de la programmation Rust fonctionne toujours : le "borrow checker". Il prévient généralement les problèmes de mémoire, les collisions dans les calculs parallèles et de nombreux autres bogues grâce à l'analyse statique du code, et cette analyse effectuera toujours des vérifications dans un bloc non sécurisé - il faut simplement beaucoup plus de travail pour écrire des constructions non sécurisées sans que le compilateur n'intervienne pour donner des conseils dans certaines situations.

Cela ne semble pas être un problème majeur pour la plupart des développeurs expérimentés - après tout, nous sommes connus pour bricoler afin d'obtenir le meilleur de nos applications et d'ouvrir des fonctions plus cool - mais cela ouvre potentiellement un trou noir qui peut conduire à de graves erreurs de configuration et à des vulnérabilités en matière de sécurité : le comportement non défini. La programmation en Rust (même lorsqu'elle est utilisée de manière non sécurisée) verrouille assez bien les possibilités de vulnérabilités par rapport au C ou au C++, mais l'invocation d'un comportement non défini peut constituer un risque.

Est-ce la fin de la dépendance à l'égard du codage sécurisé par les développeurs ?

Vous vous souvenez que j'ai dit tout à l'heure que Rust avait des composants de langages bien connus ? L'une des principales faiblesses de Rust en matière de sécurité est qu'il contient des composants de langages bien connus, à savoir le C.

Rust est toujours un "langage de programmation sûr", mais là encore, l'introduction d'un utilisateur est le point où les choses peuvent se gâter. Le développeur peut toujours le modifier pour qu'il fonctionne sans signaler les erreurs (une proposition attrayante, car cela permet de débloquer plus de capacités), et essentiellement, même dans un état sûr, les développeurs peuvent toujours être aussi "peu sûrs" qu'ils le souhaitent, car ils disposent d'une couche de conseils et de protection avant que les choses ne tournent vraiment au vinaigre.

Et les deux scénarios ci-dessus deviennent de plus en plus dangereux au fur et à mesure que nous plongeons, car les résultats de Rust sont similaires à ceux des outils d'analyse - tout comme il n'existe pas d'outil SAST/DAST/RAST/IAST de l'armée suisse qui analyse toutes les vulnérabilités, tous les vecteurs d'attaque et tous les problèmes, Rust n'en a pas non plus. Même avec Rust , certaines vulnérabilités peuvent encore être introduites assez facilement.

Le risque de comportement non défini lors de l'utilisation de Unsafe Rust peut entraîner des problèmes de débordement d'entier, alors qu'en général, même les configurations sûres n'empêcheront pas l'erreur humaine dans les mauvaises configurations de sécurité, la logique commerciale ou l'utilisation de composants avec des vulnérabilités connues. Ces problèmes constituent toujours une menace très réelle s'ils ne sont pas corrigés, et dans un environnement "supposé sûr" comme le vrai Rust, cela peut même entraîner un comportement complaisant si un codeur croit que tous les problèmes majeurs seront détectés de toute façon.

J'ai découvert que Rust n'est pas sans rappeler un mentor en programmation - un ingénieur expérimenté qui a pris le temps de s'asseoir avec un codeur moins expérimenté, examinant son travail et lui montrant les bogues potentiels, soulignant les gains d'efficacité et, dans certains cas, s'assurant qu'il n'est pas compilé tant qu'il n'est pas correct. Toutefois, il est de loin préférable que les programmeurs de rouille apprennent la théorie et s'engagent eux-mêmes à respecter les meilleures pratiques, car ce mentor pourrait bien couper les ficelles du tablier, et vous ne voudriez pas être laissé en plan.

Prêt à trouver et à corriger les vulnérabilités courantes de Rust dès maintenant ? Relevez le défi.
Voir la ressource
Voir la ressource

Rust incorpore des éléments connus et fonctionnels de langages couramment utilisés, en travaillant selon une philosophie différente qui élimine la complexité, tout en introduisant la performance et la sécurité.

Vous souhaitez en savoir plus ?

Matias Madou est expert en sécurité, chercheur, directeur technique et cofondateur de Secure Code Warrior. Matias a obtenu son doctorat en sécurité des applications à l'université de Gand, en se concentrant sur les solutions d'analyse statique. Il a ensuite rejoint Fortify aux États-Unis, où il s'est rendu compte qu'il ne suffisait pas de détecter les problèmes de code sans aider les développeurs à écrire du code sécurisé. C'est ce qui l'a incité à développer des produits qui aident les développeurs, allègent le fardeau de la sécurité et dépassent les attentes des clients. Lorsqu'il n'est pas à son bureau en tant que membre de l'équipe Awesome, il aime être sur scène pour présenter des conférences, notamment RSA Conference, BlackHat et DefCon.

Secure Code Warrior est là pour vous aider à sécuriser le code tout au long du cycle de vie du développement logiciel et à créer une culture dans laquelle la cybersécurité est une priorité. Que vous soyez responsable AppSec, développeur, CISO ou toute autre personne impliquée dans la sécurité, nous pouvons aider votre organisation à réduire les risques associés à un code non sécurisé.

Réservez une démonstration
Partager sur :
Auteur
Matias Madou, Ph.D.
Publié le 18 juin 2020

Matias Madou est expert en sécurité, chercheur, directeur technique et cofondateur de Secure Code Warrior. Matias a obtenu son doctorat en sécurité des applications à l'université de Gand, en se concentrant sur les solutions d'analyse statique. Il a ensuite rejoint Fortify aux États-Unis, où il s'est rendu compte qu'il ne suffisait pas de détecter les problèmes de code sans aider les développeurs à écrire du code sécurisé. C'est ce qui l'a incité à développer des produits qui aident les développeurs, allègent le fardeau de la sécurité et dépassent les attentes des clients. Lorsqu'il n'est pas à son bureau en tant que membre de l'équipe Awesome, il aime être sur scène pour présenter des conférences, notamment RSA Conference, BlackHat et DefCon.

Matias est un chercheur et un développeur qui possède plus de 15 ans d'expérience pratique dans le domaine de la sécurité des logiciels. Il a développé des solutions pour des entreprises telles que Fortify Software et sa propre entreprise Sensei Security. Au cours de sa carrière, Matias a dirigé de nombreux projets de recherche sur la sécurité des applications qui ont débouché sur des produits commerciaux et peut se targuer d'avoir déposé plus de 10 brevets. Lorsqu'il n'est pas à son bureau, Matias a été instructeur pour des formations avancées en matière de sécurité des applications ( courses ) et intervient régulièrement lors de conférences mondiales telles que RSA Conference, Black Hat, DefCon, BSIMM, OWASP AppSec et BruCon.

Matias est titulaire d'un doctorat en ingénierie informatique de l'Université de Gand, où il a étudié la sécurité des applications par le biais de l'obscurcissement des programmes afin de dissimuler le fonctionnement interne d'une application.

Partager sur :

Depuis quelques années, il semble que les ingénieurs logiciels du monde entier ne se lassent pas de Rust pour la programmation. Ce langage de programmation relativement nouveau, produit par Mozilla, a conquis le cœur de la communauté Stack Overflow - et, en tant que cohorte très peu encline à souffrir les imbéciles, lorsqu'ils votent quelque chose comme le"langage de programmation le plus aimé" cinq années d'affilée, il est temps que nous nous réveillions tous et que nous en prenions note.

Le langage de programmation Rust incorpore des éléments connus et fonctionnels de langages couramment utilisés, en travaillant selon une philosophie différente qui élimine la complexité, tout en introduisant la performance et la sécurité. Il s'agit d'une courbe d'apprentissage, et de nombreux développeurs n'ont pas beaucoup l'occasion de jouer avec lui - seulement 5,1 % des personnes interrogées sur Stack Overflow l'utilisent couramment. Cela mis à part, on ne peut nier qu'il s'agit d'un langage passionnant, dont la puissance de feu en matière de sécurité est bien supérieure à celle de ses prédécesseurs, comme le C et le C++. L'adoption massive de ce langage va nécessiter quelques changements, tant comportementaux que technologiques... mais pour l'instant, il continue de capter l'attention des développeurs à un niveau théorique.  

... mais attendez, nous devons mettre en lumière une autre chose : il est important de noter que Rust est un langage de programmation qui donne la priorité à la sécurité de la mémoire, et à l'éradication des bogues de sécurité qui sont liés à des problèmes courants de gestion de la mémoire. Ces problèmes sont importants (et causent sans aucun doute plus d'une migraine à l'équipe AppSec), mais ce ne sont pas les seuls défis auxquels nous sommes confrontés en matière de codage sécurisé.

Qu'est-ce que Rust empêche exactement ? Et où sommes-nous encore exposés dans le paysage de la sécurité ? Décortiquons la dernière licorne de la programmation :

La nouvelle frontière de la programmation de systèmes modernes à sécurité mémoire

L'équipe de recherche et de développement de Mozilla a travaillé sur des projets incroyables, et l'investissement dans la programmation Rust en tant que pionnier du logiciel libre ne fait pas exception. Leur vidéo d'introduction donne un aperçu de leur philosophie, avec un thème clé très clair : l'approche actuelle de la sécurité des logiciels est défectueuse, et Rust est conçu pour résoudre une grande partie de ce problème.

Cela semble trop simpliste, d'autant plus que nous sommes confrontés tous les deux jours à d'énormes violations de données - comme la récente et horrible bavure rapportée par EasyJet. Des millions d'enregistrements de données sont fréquemment compromis, presque toujours à cause d'une vulnérabilité d'application web, d'une mauvaise configuration de sécurité ou d'une attaque par hameçonnage, et des langages comme le C++ existent depuis des décennies. Cependant, les développeurs n'ont pas eu le temps de les maîtriser au point de mettre en œuvre les meilleures pratiques de codage sécurisé. Pourquoi en serait-il autrement pour Rust ? De nouveaux langages sont apparus auparavant, et ce n'est pas comme s'ils avaient trouvé un moyen d'éradiquer les vulnérabilités courantes, ou de garantir que tout code écrit est magiquement parfait lorsqu'il est compilé.

Aussi simple que soit le concept, ce sont parfois les réponses simples qui permettent de résoudre les questions complexes. Rust est, dans tous les sens du terme, une révolution dans la programmation de systèmes à mémoire sécurisée qui tient ses promesses à bien des égards... et il sauve certainement le lard des développeurs qui sont susceptibles d'introduire des erreurs qui peuvent causer de gros problèmes si elles ne sont pas détectées. Java, C, C++, et même des langages plus récents comme Kotlin et Golang, restent assez impitoyables pour le développeur non sensibilisé à la sécurité. Avec ces langages, il n'y a pas d'avertissements intégrés, pas de signes particuliers indiquant que la fonction géniale qui vient d'être compilée cache un gremlin de sécurité sous le capot.

Approfondissons donc la question :

Qu'est-ce qui rend Rust si sûr ?

En règle générale, un développeur a pour objectif principal de créer des fonctionnalités, de s'assurer qu'elles sont fonctionnelles et conviviales, voire même d'en faire une source de fierté qu'il serait heureux de faire figurer sur son curriculum vitae. Il est tout à fait normal qu'un développeur crée un excellent logiciel, le livre et passe au projet suivant. À ce stade, les équipes de sécurité recherchent des vulnérabilités et, si elles sont détectées, l'application "finie" peut être renvoyée à l'équipe qui l'a créée pour être corrigée. Le problème peut être simple, ou complètement hors de portée d'un développeur pour y remédier.

Le problème est qu'en surface, les bogues de sécurité n'étaient pas du tout apparents, et si l'analyse, les tests et l'examen manuel du code ne les détectent pas, un pirate peut potentiellement utiliser cette petite fenêtre d'opportunité pour exploiter le bogue.

Aujourd'hui, Rust cherche à empêcher de nombreuses vulnérabilités de se retrouver dans le code : il ne compile tout simplement pas s'il y a des erreurs de syntaxe ou d'autres bogues de sécurité de la mémoire qui causent des problèmes de production tout au long du cycle de vie du logiciel (SDLC). Il s'agit d'une programmation sans risque pour la mémoire, qui garantit qu'il n'y a pas d'accès à une mémoire non valide (quelle que soit la manière dont le logiciel est exécuté). Et comme 70 % de tous les bogues de sécurité résultent de problèmes liés à la gestion de la mémoire, il s'agit là d'un véritable exploit.

La rouille sera signalée et empêchée :

  • Débordement de mémoire tampon
  • Utilisation après la gratuité
  • Doublement libre
  • Déréférencement d'un pointeur nul
  • Utilisation de mémoire non initialisée

Si nous comparons un extrait de code Rust à un code C++, il apparaît clairement que l'un des deux est sûr par défaut. Regardez cet exemple de bug de débordement de mémoire tampon :

#include <iostream></iostream>
#include <string.h></string.h>
int main( void ) {
char a[3] = "12";
char b[4]= "123";
strcpy(a, b); // buffer overflow as len of b is greater than a
std::cout << a << "; " << b << std::endl;
}

Vs.

pub fn main() {
let mut a: [char; 2] = [1, 2];
let b: [char; 3] = [1, 2, 3];
a.copy_from_slice(&b);
}
Comparer un extrait de code Rust

Rust lance un avertissement de sécurité et panique en atteignant la fonction copy_from_slice en cours d'exécution pour éviter un débordement de mémoire tampon, mais pas en cours de compilation.

En ce sens, il s'agit vraiment d'un des langages "à commencer par la gauche". Il mettra en évidence les erreurs et forcera les développeurs à apprendre la bonne façon d'écrire le code afin d'éviter d'introduire des bogues de sécurité liés à la mémoire, de sorte que le respect des délais dépend de l'attention du codeur, de sa capacité à remédier aux problèmes et à rester fidèle à la voie de livraison.

L'approche de ce langage semble simple, mais cela aurait été un exploit incroyable de le faire fonctionner avec une logique aussi puissante, et il le fait. Du point de vue de la sécurité, Rust est un pas de géant... si seulement plus de gens l'utilisaient. Des entreprises comme Dropbox sont les premières à l'utiliser à grande échelle, et cela fait plaisir à voir. Mais il y a d'autres considérations à prendre en compte avant de sauter à la conclusion qu'un problème d'adoption est tout ce qui nous empêche d'avoir un avenir plus sûr.

Le bilan de la rouille.

Il y a quelques petits (ok, grands) problèmes, notamment le fait que la programmation en Rust est plus susceptible d'introduire des bogues qu'il n'y paraît. Elle ne résoudra pas les vulnérabilités du Top 10 de l'OWASP qui continuent à causer des brèches, des retards et une culture générale de techniques de codage peu sûres. Il existe également une dynamique entre l'ange et le diable, ou, comme on l'appelle plus communément : Safe Rust vs. Unsafe Rust.

Comme l'explique la documentation officielle, Safe Rust est la "vraie" forme de Rust, et Unsafe Rust inclut des fonctions qui sont considérées comme "définitivement non sûres", bien qu'elles soient parfois nécessaires - par exemple si l'intégration avec quelque chose dans un autre langage est requise. Cependant, même avec Unsafe Rust, la liste des fonctionnalités supplémentaires reste limitée. En Rust non sécurisé, il est possible d'effectuer les opérations suivantes à l'intérieur de blocs non sécurisés :

  • Déréférencer les pointeurs bruts
  • Appeler des fonctions non sûres (y compris les fonctions C, les fonctions intrinsèques du compilateur et l'allocateur brut).
  • Mettre en œuvre des caractéristiques non sûres
  • Mutation de la statique
  • Accéder aux champs des syndicats.

Même dans un mode dit "unsafe", l'un des superpouvoirs de la programmation Rust fonctionne toujours : le "borrow checker". Il prévient généralement les problèmes de mémoire, les collisions dans les calculs parallèles et de nombreux autres bogues grâce à l'analyse statique du code, et cette analyse effectuera toujours des vérifications dans un bloc non sécurisé - il faut simplement beaucoup plus de travail pour écrire des constructions non sécurisées sans que le compilateur n'intervienne pour donner des conseils dans certaines situations.

Cela ne semble pas être un problème majeur pour la plupart des développeurs expérimentés - après tout, nous sommes connus pour bricoler afin d'obtenir le meilleur de nos applications et d'ouvrir des fonctions plus cool - mais cela ouvre potentiellement un trou noir qui peut conduire à de graves erreurs de configuration et à des vulnérabilités en matière de sécurité : le comportement non défini. La programmation en Rust (même lorsqu'elle est utilisée de manière non sécurisée) verrouille assez bien les possibilités de vulnérabilités par rapport au C ou au C++, mais l'invocation d'un comportement non défini peut constituer un risque.

Est-ce la fin de la dépendance à l'égard du codage sécurisé par les développeurs ?

Vous vous souvenez que j'ai dit tout à l'heure que Rust avait des composants de langages bien connus ? L'une des principales faiblesses de Rust en matière de sécurité est qu'il contient des composants de langages bien connus, à savoir le C.

Rust est toujours un "langage de programmation sûr", mais là encore, l'introduction d'un utilisateur est le point où les choses peuvent se gâter. Le développeur peut toujours le modifier pour qu'il fonctionne sans signaler les erreurs (une proposition attrayante, car cela permet de débloquer plus de capacités), et essentiellement, même dans un état sûr, les développeurs peuvent toujours être aussi "peu sûrs" qu'ils le souhaitent, car ils disposent d'une couche de conseils et de protection avant que les choses ne tournent vraiment au vinaigre.

Et les deux scénarios ci-dessus deviennent de plus en plus dangereux au fur et à mesure que nous plongeons, car les résultats de Rust sont similaires à ceux des outils d'analyse - tout comme il n'existe pas d'outil SAST/DAST/RAST/IAST de l'armée suisse qui analyse toutes les vulnérabilités, tous les vecteurs d'attaque et tous les problèmes, Rust n'en a pas non plus. Même avec Rust , certaines vulnérabilités peuvent encore être introduites assez facilement.

Le risque de comportement non défini lors de l'utilisation de Unsafe Rust peut entraîner des problèmes de débordement d'entier, alors qu'en général, même les configurations sûres n'empêcheront pas l'erreur humaine dans les mauvaises configurations de sécurité, la logique commerciale ou l'utilisation de composants avec des vulnérabilités connues. Ces problèmes constituent toujours une menace très réelle s'ils ne sont pas corrigés, et dans un environnement "supposé sûr" comme le vrai Rust, cela peut même entraîner un comportement complaisant si un codeur croit que tous les problèmes majeurs seront détectés de toute façon.

J'ai découvert que Rust n'est pas sans rappeler un mentor en programmation - un ingénieur expérimenté qui a pris le temps de s'asseoir avec un codeur moins expérimenté, examinant son travail et lui montrant les bogues potentiels, soulignant les gains d'efficacité et, dans certains cas, s'assurant qu'il n'est pas compilé tant qu'il n'est pas correct. Toutefois, il est de loin préférable que les programmeurs de rouille apprennent la théorie et s'engagent eux-mêmes à respecter les meilleures pratiques, car ce mentor pourrait bien couper les ficelles du tablier, et vous ne voudriez pas être laissé en plan.

Prêt à trouver et à corriger les vulnérabilités courantes de Rust dès maintenant ? Relevez le défi.
Voir la ressource
Voir la ressource

Remplissez le formulaire ci-dessous pour télécharger le rapport

Nous aimerions que vous nous autorisiez à vous envoyer des informations sur nos produits et/ou sur des sujets liés au codage sécurisé. Nous traiterons toujours vos données personnelles avec le plus grand soin et ne les vendrons jamais à d'autres entreprises à des fins de marketing.

Soumettre
Pour soumettre le formulaire, veuillez activer les cookies "Analytics". N'hésitez pas à les désactiver à nouveau une fois que vous aurez terminé.

Depuis quelques années, il semble que les ingénieurs logiciels du monde entier ne se lassent pas de Rust pour la programmation. Ce langage de programmation relativement nouveau, produit par Mozilla, a conquis le cœur de la communauté Stack Overflow - et, en tant que cohorte très peu encline à souffrir les imbéciles, lorsqu'ils votent quelque chose comme le"langage de programmation le plus aimé" cinq années d'affilée, il est temps que nous nous réveillions tous et que nous en prenions note.

Le langage de programmation Rust incorpore des éléments connus et fonctionnels de langages couramment utilisés, en travaillant selon une philosophie différente qui élimine la complexité, tout en introduisant la performance et la sécurité. Il s'agit d'une courbe d'apprentissage, et de nombreux développeurs n'ont pas beaucoup l'occasion de jouer avec lui - seulement 5,1 % des personnes interrogées sur Stack Overflow l'utilisent couramment. Cela mis à part, on ne peut nier qu'il s'agit d'un langage passionnant, dont la puissance de feu en matière de sécurité est bien supérieure à celle de ses prédécesseurs, comme le C et le C++. L'adoption massive de ce langage va nécessiter quelques changements, tant comportementaux que technologiques... mais pour l'instant, il continue de capter l'attention des développeurs à un niveau théorique.  

... mais attendez, nous devons mettre en lumière une autre chose : il est important de noter que Rust est un langage de programmation qui donne la priorité à la sécurité de la mémoire, et à l'éradication des bogues de sécurité qui sont liés à des problèmes courants de gestion de la mémoire. Ces problèmes sont importants (et causent sans aucun doute plus d'une migraine à l'équipe AppSec), mais ce ne sont pas les seuls défis auxquels nous sommes confrontés en matière de codage sécurisé.

Qu'est-ce que Rust empêche exactement ? Et où sommes-nous encore exposés dans le paysage de la sécurité ? Décortiquons la dernière licorne de la programmation :

La nouvelle frontière de la programmation de systèmes modernes à sécurité mémoire

L'équipe de recherche et de développement de Mozilla a travaillé sur des projets incroyables, et l'investissement dans la programmation Rust en tant que pionnier du logiciel libre ne fait pas exception. Leur vidéo d'introduction donne un aperçu de leur philosophie, avec un thème clé très clair : l'approche actuelle de la sécurité des logiciels est défectueuse, et Rust est conçu pour résoudre une grande partie de ce problème.

Cela semble trop simpliste, d'autant plus que nous sommes confrontés tous les deux jours à d'énormes violations de données - comme la récente et horrible bavure rapportée par EasyJet. Des millions d'enregistrements de données sont fréquemment compromis, presque toujours à cause d'une vulnérabilité d'application web, d'une mauvaise configuration de sécurité ou d'une attaque par hameçonnage, et des langages comme le C++ existent depuis des décennies. Cependant, les développeurs n'ont pas eu le temps de les maîtriser au point de mettre en œuvre les meilleures pratiques de codage sécurisé. Pourquoi en serait-il autrement pour Rust ? De nouveaux langages sont apparus auparavant, et ce n'est pas comme s'ils avaient trouvé un moyen d'éradiquer les vulnérabilités courantes, ou de garantir que tout code écrit est magiquement parfait lorsqu'il est compilé.

Aussi simple que soit le concept, ce sont parfois les réponses simples qui permettent de résoudre les questions complexes. Rust est, dans tous les sens du terme, une révolution dans la programmation de systèmes à mémoire sécurisée qui tient ses promesses à bien des égards... et il sauve certainement le lard des développeurs qui sont susceptibles d'introduire des erreurs qui peuvent causer de gros problèmes si elles ne sont pas détectées. Java, C, C++, et même des langages plus récents comme Kotlin et Golang, restent assez impitoyables pour le développeur non sensibilisé à la sécurité. Avec ces langages, il n'y a pas d'avertissements intégrés, pas de signes particuliers indiquant que la fonction géniale qui vient d'être compilée cache un gremlin de sécurité sous le capot.

Approfondissons donc la question :

Qu'est-ce qui rend Rust si sûr ?

En règle générale, un développeur a pour objectif principal de créer des fonctionnalités, de s'assurer qu'elles sont fonctionnelles et conviviales, voire même d'en faire une source de fierté qu'il serait heureux de faire figurer sur son curriculum vitae. Il est tout à fait normal qu'un développeur crée un excellent logiciel, le livre et passe au projet suivant. À ce stade, les équipes de sécurité recherchent des vulnérabilités et, si elles sont détectées, l'application "finie" peut être renvoyée à l'équipe qui l'a créée pour être corrigée. Le problème peut être simple, ou complètement hors de portée d'un développeur pour y remédier.

Le problème est qu'en surface, les bogues de sécurité n'étaient pas du tout apparents, et si l'analyse, les tests et l'examen manuel du code ne les détectent pas, un pirate peut potentiellement utiliser cette petite fenêtre d'opportunité pour exploiter le bogue.

Aujourd'hui, Rust cherche à empêcher de nombreuses vulnérabilités de se retrouver dans le code : il ne compile tout simplement pas s'il y a des erreurs de syntaxe ou d'autres bogues de sécurité de la mémoire qui causent des problèmes de production tout au long du cycle de vie du logiciel (SDLC). Il s'agit d'une programmation sans risque pour la mémoire, qui garantit qu'il n'y a pas d'accès à une mémoire non valide (quelle que soit la manière dont le logiciel est exécuté). Et comme 70 % de tous les bogues de sécurité résultent de problèmes liés à la gestion de la mémoire, il s'agit là d'un véritable exploit.

La rouille sera signalée et empêchée :

  • Débordement de mémoire tampon
  • Utilisation après la gratuité
  • Doublement libre
  • Déréférencement d'un pointeur nul
  • Utilisation de mémoire non initialisée

Si nous comparons un extrait de code Rust à un code C++, il apparaît clairement que l'un des deux est sûr par défaut. Regardez cet exemple de bug de débordement de mémoire tampon :

#include <iostream></iostream>
#include <string.h></string.h>
int main( void ) {
char a[3] = "12";
char b[4]= "123";
strcpy(a, b); // buffer overflow as len of b is greater than a
std::cout << a << "; " << b << std::endl;
}

Vs.

pub fn main() {
let mut a: [char; 2] = [1, 2];
let b: [char; 3] = [1, 2, 3];
a.copy_from_slice(&b);
}
Comparer un extrait de code Rust

Rust lance un avertissement de sécurité et panique en atteignant la fonction copy_from_slice en cours d'exécution pour éviter un débordement de mémoire tampon, mais pas en cours de compilation.

En ce sens, il s'agit vraiment d'un des langages "à commencer par la gauche". Il mettra en évidence les erreurs et forcera les développeurs à apprendre la bonne façon d'écrire le code afin d'éviter d'introduire des bogues de sécurité liés à la mémoire, de sorte que le respect des délais dépend de l'attention du codeur, de sa capacité à remédier aux problèmes et à rester fidèle à la voie de livraison.

L'approche de ce langage semble simple, mais cela aurait été un exploit incroyable de le faire fonctionner avec une logique aussi puissante, et il le fait. Du point de vue de la sécurité, Rust est un pas de géant... si seulement plus de gens l'utilisaient. Des entreprises comme Dropbox sont les premières à l'utiliser à grande échelle, et cela fait plaisir à voir. Mais il y a d'autres considérations à prendre en compte avant de sauter à la conclusion qu'un problème d'adoption est tout ce qui nous empêche d'avoir un avenir plus sûr.

Le bilan de la rouille.

Il y a quelques petits (ok, grands) problèmes, notamment le fait que la programmation en Rust est plus susceptible d'introduire des bogues qu'il n'y paraît. Elle ne résoudra pas les vulnérabilités du Top 10 de l'OWASP qui continuent à causer des brèches, des retards et une culture générale de techniques de codage peu sûres. Il existe également une dynamique entre l'ange et le diable, ou, comme on l'appelle plus communément : Safe Rust vs. Unsafe Rust.

Comme l'explique la documentation officielle, Safe Rust est la "vraie" forme de Rust, et Unsafe Rust inclut des fonctions qui sont considérées comme "définitivement non sûres", bien qu'elles soient parfois nécessaires - par exemple si l'intégration avec quelque chose dans un autre langage est requise. Cependant, même avec Unsafe Rust, la liste des fonctionnalités supplémentaires reste limitée. En Rust non sécurisé, il est possible d'effectuer les opérations suivantes à l'intérieur de blocs non sécurisés :

  • Déréférencer les pointeurs bruts
  • Appeler des fonctions non sûres (y compris les fonctions C, les fonctions intrinsèques du compilateur et l'allocateur brut).
  • Mettre en œuvre des caractéristiques non sûres
  • Mutation de la statique
  • Accéder aux champs des syndicats.

Même dans un mode dit "unsafe", l'un des superpouvoirs de la programmation Rust fonctionne toujours : le "borrow checker". Il prévient généralement les problèmes de mémoire, les collisions dans les calculs parallèles et de nombreux autres bogues grâce à l'analyse statique du code, et cette analyse effectuera toujours des vérifications dans un bloc non sécurisé - il faut simplement beaucoup plus de travail pour écrire des constructions non sécurisées sans que le compilateur n'intervienne pour donner des conseils dans certaines situations.

Cela ne semble pas être un problème majeur pour la plupart des développeurs expérimentés - après tout, nous sommes connus pour bricoler afin d'obtenir le meilleur de nos applications et d'ouvrir des fonctions plus cool - mais cela ouvre potentiellement un trou noir qui peut conduire à de graves erreurs de configuration et à des vulnérabilités en matière de sécurité : le comportement non défini. La programmation en Rust (même lorsqu'elle est utilisée de manière non sécurisée) verrouille assez bien les possibilités de vulnérabilités par rapport au C ou au C++, mais l'invocation d'un comportement non défini peut constituer un risque.

Est-ce la fin de la dépendance à l'égard du codage sécurisé par les développeurs ?

Vous vous souvenez que j'ai dit tout à l'heure que Rust avait des composants de langages bien connus ? L'une des principales faiblesses de Rust en matière de sécurité est qu'il contient des composants de langages bien connus, à savoir le C.

Rust est toujours un "langage de programmation sûr", mais là encore, l'introduction d'un utilisateur est le point où les choses peuvent se gâter. Le développeur peut toujours le modifier pour qu'il fonctionne sans signaler les erreurs (une proposition attrayante, car cela permet de débloquer plus de capacités), et essentiellement, même dans un état sûr, les développeurs peuvent toujours être aussi "peu sûrs" qu'ils le souhaitent, car ils disposent d'une couche de conseils et de protection avant que les choses ne tournent vraiment au vinaigre.

Et les deux scénarios ci-dessus deviennent de plus en plus dangereux au fur et à mesure que nous plongeons, car les résultats de Rust sont similaires à ceux des outils d'analyse - tout comme il n'existe pas d'outil SAST/DAST/RAST/IAST de l'armée suisse qui analyse toutes les vulnérabilités, tous les vecteurs d'attaque et tous les problèmes, Rust n'en a pas non plus. Même avec Rust , certaines vulnérabilités peuvent encore être introduites assez facilement.

Le risque de comportement non défini lors de l'utilisation de Unsafe Rust peut entraîner des problèmes de débordement d'entier, alors qu'en général, même les configurations sûres n'empêcheront pas l'erreur humaine dans les mauvaises configurations de sécurité, la logique commerciale ou l'utilisation de composants avec des vulnérabilités connues. Ces problèmes constituent toujours une menace très réelle s'ils ne sont pas corrigés, et dans un environnement "supposé sûr" comme le vrai Rust, cela peut même entraîner un comportement complaisant si un codeur croit que tous les problèmes majeurs seront détectés de toute façon.

J'ai découvert que Rust n'est pas sans rappeler un mentor en programmation - un ingénieur expérimenté qui a pris le temps de s'asseoir avec un codeur moins expérimenté, examinant son travail et lui montrant les bogues potentiels, soulignant les gains d'efficacité et, dans certains cas, s'assurant qu'il n'est pas compilé tant qu'il n'est pas correct. Toutefois, il est de loin préférable que les programmeurs de rouille apprennent la théorie et s'engagent eux-mêmes à respecter les meilleures pratiques, car ce mentor pourrait bien couper les ficelles du tablier, et vous ne voudriez pas être laissé en plan.

Prêt à trouver et à corriger les vulnérabilités courantes de Rust dès maintenant ? Relevez le défi.
Commencez

Cliquez sur le lien ci-dessous et téléchargez le PDF de cette ressource.

Secure Code Warrior est là pour vous aider à sécuriser le code tout au long du cycle de vie du développement logiciel et à créer une culture dans laquelle la cybersécurité est une priorité. Que vous soyez responsable AppSec, développeur, CISO ou toute autre personne impliquée dans la sécurité, nous pouvons aider votre organisation à réduire les risques associés à un code non sécurisé.

Voir le rapportRéservez une démonstration
Télécharger le PDF
Voir la ressource
Partager sur :
Vous souhaitez en savoir plus ?

Partager sur :
Auteur
Matias Madou, Ph.D.
Publié le 18 juin 2020

Matias Madou est expert en sécurité, chercheur, directeur technique et cofondateur de Secure Code Warrior. Matias a obtenu son doctorat en sécurité des applications à l'université de Gand, en se concentrant sur les solutions d'analyse statique. Il a ensuite rejoint Fortify aux États-Unis, où il s'est rendu compte qu'il ne suffisait pas de détecter les problèmes de code sans aider les développeurs à écrire du code sécurisé. C'est ce qui l'a incité à développer des produits qui aident les développeurs, allègent le fardeau de la sécurité et dépassent les attentes des clients. Lorsqu'il n'est pas à son bureau en tant que membre de l'équipe Awesome, il aime être sur scène pour présenter des conférences, notamment RSA Conference, BlackHat et DefCon.

Matias est un chercheur et un développeur qui possède plus de 15 ans d'expérience pratique dans le domaine de la sécurité des logiciels. Il a développé des solutions pour des entreprises telles que Fortify Software et sa propre entreprise Sensei Security. Au cours de sa carrière, Matias a dirigé de nombreux projets de recherche sur la sécurité des applications qui ont débouché sur des produits commerciaux et peut se targuer d'avoir déposé plus de 10 brevets. Lorsqu'il n'est pas à son bureau, Matias a été instructeur pour des formations avancées en matière de sécurité des applications ( courses ) et intervient régulièrement lors de conférences mondiales telles que RSA Conference, Black Hat, DefCon, BSIMM, OWASP AppSec et BruCon.

Matias est titulaire d'un doctorat en ingénierie informatique de l'Université de Gand, où il a étudié la sécurité des applications par le biais de l'obscurcissement des programmes afin de dissimuler le fonctionnement interne d'une application.

Partager sur :

Depuis quelques années, il semble que les ingénieurs logiciels du monde entier ne se lassent pas de Rust pour la programmation. Ce langage de programmation relativement nouveau, produit par Mozilla, a conquis le cœur de la communauté Stack Overflow - et, en tant que cohorte très peu encline à souffrir les imbéciles, lorsqu'ils votent quelque chose comme le"langage de programmation le plus aimé" cinq années d'affilée, il est temps que nous nous réveillions tous et que nous en prenions note.

Le langage de programmation Rust incorpore des éléments connus et fonctionnels de langages couramment utilisés, en travaillant selon une philosophie différente qui élimine la complexité, tout en introduisant la performance et la sécurité. Il s'agit d'une courbe d'apprentissage, et de nombreux développeurs n'ont pas beaucoup l'occasion de jouer avec lui - seulement 5,1 % des personnes interrogées sur Stack Overflow l'utilisent couramment. Cela mis à part, on ne peut nier qu'il s'agit d'un langage passionnant, dont la puissance de feu en matière de sécurité est bien supérieure à celle de ses prédécesseurs, comme le C et le C++. L'adoption massive de ce langage va nécessiter quelques changements, tant comportementaux que technologiques... mais pour l'instant, il continue de capter l'attention des développeurs à un niveau théorique.  

... mais attendez, nous devons mettre en lumière une autre chose : il est important de noter que Rust est un langage de programmation qui donne la priorité à la sécurité de la mémoire, et à l'éradication des bogues de sécurité qui sont liés à des problèmes courants de gestion de la mémoire. Ces problèmes sont importants (et causent sans aucun doute plus d'une migraine à l'équipe AppSec), mais ce ne sont pas les seuls défis auxquels nous sommes confrontés en matière de codage sécurisé.

Qu'est-ce que Rust empêche exactement ? Et où sommes-nous encore exposés dans le paysage de la sécurité ? Décortiquons la dernière licorne de la programmation :

La nouvelle frontière de la programmation de systèmes modernes à sécurité mémoire

L'équipe de recherche et de développement de Mozilla a travaillé sur des projets incroyables, et l'investissement dans la programmation Rust en tant que pionnier du logiciel libre ne fait pas exception. Leur vidéo d'introduction donne un aperçu de leur philosophie, avec un thème clé très clair : l'approche actuelle de la sécurité des logiciels est défectueuse, et Rust est conçu pour résoudre une grande partie de ce problème.

Cela semble trop simpliste, d'autant plus que nous sommes confrontés tous les deux jours à d'énormes violations de données - comme la récente et horrible bavure rapportée par EasyJet. Des millions d'enregistrements de données sont fréquemment compromis, presque toujours à cause d'une vulnérabilité d'application web, d'une mauvaise configuration de sécurité ou d'une attaque par hameçonnage, et des langages comme le C++ existent depuis des décennies. Cependant, les développeurs n'ont pas eu le temps de les maîtriser au point de mettre en œuvre les meilleures pratiques de codage sécurisé. Pourquoi en serait-il autrement pour Rust ? De nouveaux langages sont apparus auparavant, et ce n'est pas comme s'ils avaient trouvé un moyen d'éradiquer les vulnérabilités courantes, ou de garantir que tout code écrit est magiquement parfait lorsqu'il est compilé.

Aussi simple que soit le concept, ce sont parfois les réponses simples qui permettent de résoudre les questions complexes. Rust est, dans tous les sens du terme, une révolution dans la programmation de systèmes à mémoire sécurisée qui tient ses promesses à bien des égards... et il sauve certainement le lard des développeurs qui sont susceptibles d'introduire des erreurs qui peuvent causer de gros problèmes si elles ne sont pas détectées. Java, C, C++, et même des langages plus récents comme Kotlin et Golang, restent assez impitoyables pour le développeur non sensibilisé à la sécurité. Avec ces langages, il n'y a pas d'avertissements intégrés, pas de signes particuliers indiquant que la fonction géniale qui vient d'être compilée cache un gremlin de sécurité sous le capot.

Approfondissons donc la question :

Qu'est-ce qui rend Rust si sûr ?

En règle générale, un développeur a pour objectif principal de créer des fonctionnalités, de s'assurer qu'elles sont fonctionnelles et conviviales, voire même d'en faire une source de fierté qu'il serait heureux de faire figurer sur son curriculum vitae. Il est tout à fait normal qu'un développeur crée un excellent logiciel, le livre et passe au projet suivant. À ce stade, les équipes de sécurité recherchent des vulnérabilités et, si elles sont détectées, l'application "finie" peut être renvoyée à l'équipe qui l'a créée pour être corrigée. Le problème peut être simple, ou complètement hors de portée d'un développeur pour y remédier.

Le problème est qu'en surface, les bogues de sécurité n'étaient pas du tout apparents, et si l'analyse, les tests et l'examen manuel du code ne les détectent pas, un pirate peut potentiellement utiliser cette petite fenêtre d'opportunité pour exploiter le bogue.

Aujourd'hui, Rust cherche à empêcher de nombreuses vulnérabilités de se retrouver dans le code : il ne compile tout simplement pas s'il y a des erreurs de syntaxe ou d'autres bogues de sécurité de la mémoire qui causent des problèmes de production tout au long du cycle de vie du logiciel (SDLC). Il s'agit d'une programmation sans risque pour la mémoire, qui garantit qu'il n'y a pas d'accès à une mémoire non valide (quelle que soit la manière dont le logiciel est exécuté). Et comme 70 % de tous les bogues de sécurité résultent de problèmes liés à la gestion de la mémoire, il s'agit là d'un véritable exploit.

La rouille sera signalée et empêchée :

  • Débordement de mémoire tampon
  • Utilisation après la gratuité
  • Doublement libre
  • Déréférencement d'un pointeur nul
  • Utilisation de mémoire non initialisée

Si nous comparons un extrait de code Rust à un code C++, il apparaît clairement que l'un des deux est sûr par défaut. Regardez cet exemple de bug de débordement de mémoire tampon :

#include <iostream></iostream>
#include <string.h></string.h>
int main( void ) {
char a[3] = "12";
char b[4]= "123";
strcpy(a, b); // buffer overflow as len of b is greater than a
std::cout << a << "; " << b << std::endl;
}

Vs.

pub fn main() {
let mut a: [char; 2] = [1, 2];
let b: [char; 3] = [1, 2, 3];
a.copy_from_slice(&b);
}
Comparer un extrait de code Rust

Rust lance un avertissement de sécurité et panique en atteignant la fonction copy_from_slice en cours d'exécution pour éviter un débordement de mémoire tampon, mais pas en cours de compilation.

En ce sens, il s'agit vraiment d'un des langages "à commencer par la gauche". Il mettra en évidence les erreurs et forcera les développeurs à apprendre la bonne façon d'écrire le code afin d'éviter d'introduire des bogues de sécurité liés à la mémoire, de sorte que le respect des délais dépend de l'attention du codeur, de sa capacité à remédier aux problèmes et à rester fidèle à la voie de livraison.

L'approche de ce langage semble simple, mais cela aurait été un exploit incroyable de le faire fonctionner avec une logique aussi puissante, et il le fait. Du point de vue de la sécurité, Rust est un pas de géant... si seulement plus de gens l'utilisaient. Des entreprises comme Dropbox sont les premières à l'utiliser à grande échelle, et cela fait plaisir à voir. Mais il y a d'autres considérations à prendre en compte avant de sauter à la conclusion qu'un problème d'adoption est tout ce qui nous empêche d'avoir un avenir plus sûr.

Le bilan de la rouille.

Il y a quelques petits (ok, grands) problèmes, notamment le fait que la programmation en Rust est plus susceptible d'introduire des bogues qu'il n'y paraît. Elle ne résoudra pas les vulnérabilités du Top 10 de l'OWASP qui continuent à causer des brèches, des retards et une culture générale de techniques de codage peu sûres. Il existe également une dynamique entre l'ange et le diable, ou, comme on l'appelle plus communément : Safe Rust vs. Unsafe Rust.

Comme l'explique la documentation officielle, Safe Rust est la "vraie" forme de Rust, et Unsafe Rust inclut des fonctions qui sont considérées comme "définitivement non sûres", bien qu'elles soient parfois nécessaires - par exemple si l'intégration avec quelque chose dans un autre langage est requise. Cependant, même avec Unsafe Rust, la liste des fonctionnalités supplémentaires reste limitée. En Rust non sécurisé, il est possible d'effectuer les opérations suivantes à l'intérieur de blocs non sécurisés :

  • Déréférencer les pointeurs bruts
  • Appeler des fonctions non sûres (y compris les fonctions C, les fonctions intrinsèques du compilateur et l'allocateur brut).
  • Mettre en œuvre des caractéristiques non sûres
  • Mutation de la statique
  • Accéder aux champs des syndicats.

Même dans un mode dit "unsafe", l'un des superpouvoirs de la programmation Rust fonctionne toujours : le "borrow checker". Il prévient généralement les problèmes de mémoire, les collisions dans les calculs parallèles et de nombreux autres bogues grâce à l'analyse statique du code, et cette analyse effectuera toujours des vérifications dans un bloc non sécurisé - il faut simplement beaucoup plus de travail pour écrire des constructions non sécurisées sans que le compilateur n'intervienne pour donner des conseils dans certaines situations.

Cela ne semble pas être un problème majeur pour la plupart des développeurs expérimentés - après tout, nous sommes connus pour bricoler afin d'obtenir le meilleur de nos applications et d'ouvrir des fonctions plus cool - mais cela ouvre potentiellement un trou noir qui peut conduire à de graves erreurs de configuration et à des vulnérabilités en matière de sécurité : le comportement non défini. La programmation en Rust (même lorsqu'elle est utilisée de manière non sécurisée) verrouille assez bien les possibilités de vulnérabilités par rapport au C ou au C++, mais l'invocation d'un comportement non défini peut constituer un risque.

Est-ce la fin de la dépendance à l'égard du codage sécurisé par les développeurs ?

Vous vous souvenez que j'ai dit tout à l'heure que Rust avait des composants de langages bien connus ? L'une des principales faiblesses de Rust en matière de sécurité est qu'il contient des composants de langages bien connus, à savoir le C.

Rust est toujours un "langage de programmation sûr", mais là encore, l'introduction d'un utilisateur est le point où les choses peuvent se gâter. Le développeur peut toujours le modifier pour qu'il fonctionne sans signaler les erreurs (une proposition attrayante, car cela permet de débloquer plus de capacités), et essentiellement, même dans un état sûr, les développeurs peuvent toujours être aussi "peu sûrs" qu'ils le souhaitent, car ils disposent d'une couche de conseils et de protection avant que les choses ne tournent vraiment au vinaigre.

Et les deux scénarios ci-dessus deviennent de plus en plus dangereux au fur et à mesure que nous plongeons, car les résultats de Rust sont similaires à ceux des outils d'analyse - tout comme il n'existe pas d'outil SAST/DAST/RAST/IAST de l'armée suisse qui analyse toutes les vulnérabilités, tous les vecteurs d'attaque et tous les problèmes, Rust n'en a pas non plus. Même avec Rust , certaines vulnérabilités peuvent encore être introduites assez facilement.

Le risque de comportement non défini lors de l'utilisation de Unsafe Rust peut entraîner des problèmes de débordement d'entier, alors qu'en général, même les configurations sûres n'empêcheront pas l'erreur humaine dans les mauvaises configurations de sécurité, la logique commerciale ou l'utilisation de composants avec des vulnérabilités connues. Ces problèmes constituent toujours une menace très réelle s'ils ne sont pas corrigés, et dans un environnement "supposé sûr" comme le vrai Rust, cela peut même entraîner un comportement complaisant si un codeur croit que tous les problèmes majeurs seront détectés de toute façon.

J'ai découvert que Rust n'est pas sans rappeler un mentor en programmation - un ingénieur expérimenté qui a pris le temps de s'asseoir avec un codeur moins expérimenté, examinant son travail et lui montrant les bogues potentiels, soulignant les gains d'efficacité et, dans certains cas, s'assurant qu'il n'est pas compilé tant qu'il n'est pas correct. Toutefois, il est de loin préférable que les programmeurs de rouille apprennent la théorie et s'engagent eux-mêmes à respecter les meilleures pratiques, car ce mentor pourrait bien couper les ficelles du tablier, et vous ne voudriez pas être laissé en plan.

Prêt à trouver et à corriger les vulnérabilités courantes de Rust dès maintenant ? Relevez le défi.

Table des matières

Télécharger le PDF
Voir la ressource
Vous souhaitez en savoir plus ?

Matias Madou est expert en sécurité, chercheur, directeur technique et cofondateur de Secure Code Warrior. Matias a obtenu son doctorat en sécurité des applications à l'université de Gand, en se concentrant sur les solutions d'analyse statique. Il a ensuite rejoint Fortify aux États-Unis, où il s'est rendu compte qu'il ne suffisait pas de détecter les problèmes de code sans aider les développeurs à écrire du code sécurisé. C'est ce qui l'a incité à développer des produits qui aident les développeurs, allègent le fardeau de la sécurité et dépassent les attentes des clients. Lorsqu'il n'est pas à son bureau en tant que membre de l'équipe Awesome, il aime être sur scène pour présenter des conférences, notamment RSA Conference, BlackHat et DefCon.

Secure Code Warrior est là pour vous aider à sécuriser le code tout au long du cycle de vie du développement logiciel et à créer une culture dans laquelle la cybersécurité est une priorité. Que vous soyez responsable AppSec, développeur, CISO ou toute autre personne impliquée dans la sécurité, nous pouvons aider votre organisation à réduire les risques associés à un code non sécurisé.

Réservez une démonstrationTélécharger
Partager sur :
Centre de ressources

Ressources pour vous aider à démarrer

Plus d'articles
Centre de ressources

Ressources pour vous aider à démarrer

Plus d'articles