Des chercheurs de l'université de Cambridge ont publié une technique de substitution discrète de code malveillant dans des textes sources évalués par des pairs. La méthode d'attaque préparée (CVE-2021-42574) est appelée Trojan Source et repose sur la formation de texte qui apparaît différemment pour le compilateur/interpréteur et pour la personne examinant le code. Des exemples d'application de la méthode ont été démontrés pour divers compilateurs et interprètes pour les langages C, C++ (gcc et clang), C#, JavaScript (Node.js), Java (OpenJDK 16), Rust, Go et Python.
La méthode se base sur l'utilisation de caractères Unicode spéciaux dans les commentaires du code, qui modifient l'ordre d'affichage du texte bidirectionnel. Grâce à ces caractères de contrôle, certaines parties du texte peuvent être affichées de gauche à droite, tandis que d'autres peuvent l'être de droite à gauche. Dans la pratique quotidienne, de tels caractères de contrôle peuvent être utilisés, par exemple, pour insérer des lignes en hébreu ou en arabe dans un fichier de code. Mais si l'on combine des chaînes de direction de texte différente dans une même ligne, à l'aide desdits symboles, des extraits de texte affichés de droite à gauche peuvent recouvrir du texte normal affiché de gauche à droite.
En utilisant cette méthode, il est possible d'ajouter une construction malveillante dans le code, mais ensuite de rendre ce texte avec la construction invisible lors de l'examen du code, en ajoutant à un commentaire suivant ou à l'intérieur d'un littéral des caractères affichés de droite à gauche, ce qui entraînera le chevauchement de l'insertion malveillante avec des symboles complètement différents. Ce code restera sémantiquement correct, mais sera interprété et affiché différemment.

Lors de l'examen du code, le développeur sera confronté à l'ordre visuel d'affichage des caractères et verra dans un éditeur de texte moderne, une interface web ou un IDE un commentaire sans susciter de soupçons, mais le compilateur et l'interpréteur utiliseront l'ordre logique des caractères et traiteront l'insertion malveillante telle quelle, sans prêter attention au texte bidirectionnel dans le commentaire. Différents éditeurs de code populaires (VS Code, Emacs, Atom) ainsi que les interfaces de visualisation de code dans les dépôts (GitHub, Gitlab, BitBucket et tous les produits Atlassian) sont concernés par le problème.

Plusieurs méthodes d'utilisation du processus pour réaliser des actions malveillantes sont mises en avant : l'ajout d'une instruction cachée «return», provoquant la fin de l'exécution de la fonction prématurément ; le commentaire d'expressions normalement visibles comme des constructions valides (par exemple, pour désactiver des vérifications cruciales) ; l'attribution d'autres valeurs de chaîne, entraînant l'échec de la vérification des chaînes.
Par exemple, un attaquant pourrait proposer une modification incluant la ligne : if access_level != «user{U+202E} {U+2066}// Check if admin{U+2069} {U+2066}» {
qui sera affichée dans l'interface pour révision comme if access_level != «user» { // Check if admin
De plus, une autre variante d'attaque (CVE-2021-42694) a été proposée, liée à l'utilisation d'homoglyphes, des symboles ressemblant visuellement mais ayant des significations différentes et ayant différents codes unicode (par exemple, le symbole «ɑ» ressemble à «a», «ɡ» à «g», «ɩ» à «l»). De tels symboles peuvent être utilisés dans certains langages pour nommer des fonctions et des variables afin d'induire en erreur les développeurs. Par exemple, deux fonctions peuvent être définies avec des noms indiscernables exécutant différentes actions. Sans une analyse approfondie, il est impossible de comprendre immédiatement laquelle de ces deux fonctions est appelée à un endroit donné.

Comme mesure de protection, il est recommandé de mettre en œuvre dans les compilateurs, interprétateurs et outils de construction prenant en charge les symboles Unicode, un affichage d'erreur ou d'avertissement en cas de présence dans les commentaires, littéraux de chaîne ou identifiants de caractères de contrôle impairs, changeant la direction d'affichage (U+202A, U+202B, U+202C, U+202D, U+202E, U+2066, U+2067, U+2068, U+2069, U+061C, U+200E et U+200F). De tels symboles devraient également être explicitement interdits dans les spécifications des langages de programmation et devraient être pris en compte dans les éditeurs de code et les interfaces de gestion des dépôts.
Addendum 1 : Des correctifs pour remédier à la vulnérabilité ont été préparés pour GCC, LLVM/Clang, Rust, Go, Python et binutils. Le problème a également été résolu par GitHub, Bitbucket et Jira. Un correctif pour GitLab est en cours de préparation. Pour identifier le code problématique, il est proposé d'utiliser la commande : grep -r $'[\u061C\u200E\u200F\u202A\u202B\u202C\u202D\u202E\u2066\u2067\u2068\u2069]' /path/to/source
Ajout 2 : Russ Cox, l'un des développeurs du système d'exploitation Plan 9 et du langage de programmation Go, a critiqué l'attention excessive portée à la méthode d'attaque décrite, qui est connue depuis longtemps (Go, Rust, C++, Ruby) et n'a pas été prise au sérieux. Selon Cox, le problème concerne principalement la manière dont l'information est affichée dans les éditeurs de code et les interfaces web, et peut être résolu en utilisant les bons outils et analyseurs de code lors de la révision. Par conséquent, au lieu d'attirer l'attention sur des attaques purement théoriques, il serait plus judicieux de se concentrer sur l'amélioration des processus de révision du code et des dépendances.
Russ Cox pense également que les compilateurs ne sont pas le bon endroit pour résoudre le problème, car en interdisant les caractères dangereux au niveau du compilateur, il reste un large éventail d'outils où l'utilisation de ces caractères est encore autorisée, tels que les systèmes de build, les assembleurs, les gestionnaires de paquets et divers analyseurs de configuration et de données. Par exemple, le projet Rust a interdit le traitement du code LTR/RTL dans le compilateur, mais n'a pas ajouté de correctif dans le gestionnaire de paquets Cargo, ce qui permet une attaque similaire via le fichier Cargo.toml. De même, des fichiers comme BUILD.bazel, CMakefile, Cargo.toml, Dockerfile, GNUmakefile, Makefile, go.mod, package.json, pom.xml et requirements.txt peuvent également être sources d'attaques.
Source : opennet.ru
