Un article récemment publié fournit un logo et une finition soignée pour une ancienne vulnérabilité concernant la capacité de certains caractères Unicode à être rendus différemment pour les examinateurs humains que les machines qui exécutent les instructions.
- Le code peut avoir l’intention de dérouter un lecteur humain pour qu’il comprenne mal le code en fonction de la façon dont le compilateur lit l’encodage (en particulier les caractères Unicode). Le résultat escompté serait d’exécuter quelque chose qu’un humain non confus ne permettrait pas.
- Un réviseur de code humain utilisant un éditeur de texte brut ou un éditeur avec une coloration syntaxique inexacte peut manquer l’impact de ces caractères de contrôle. La plupart des IDE et des éditeurs de code utilisent des arbres d’analyse et rendent les caractères Unicode visibles afin qu’ils soient plus faciles à comprendre pour quelqu’un.
- Les développeurs qui discutent de cette vulnérabilité de Trojan Source peuvent profiter de l’occasion pour faire des jeux de mots.
Quelle est la source du cheval de Troie ?
La source du cheval de Troie est une combinaison de caractères de contrôle Unicode qui a pour but de faire croire à un humain que le code fait une chose tout en obligeant la machine à en faire une autre. Il s’agit principalement de la possibilité de modifier certains caractères de contrôle, comme la commutation de l’encodage de droite à gauche ou d’encoder des lettres d’apparence similaire dans différents jeux de caractères.
L’article cite également la confusion des noms de fonctions où deux méthodes ont le même nom mais pas non plus. Il utilise l’exemple de deux méthodes sayHello, dont l’une utilise le latin H et une autre fonction utilisant le cyrillique H (elles se ressemblent toutes les deux). Le code qui appelle la méthode référencera la fonction analysée par la machine qui peut faire la différence.
Le code suivant représente l’exemple de ces caractères de contrôle pour faire croire à quelqu’un que le code n’imprimera « Vous êtes un administrateur » que si le niveau d’accès n’est pas « utilisateur ». Le code effectue en fait une vérification différente, cachant un commentaire à l’intérieur d’une chaîne, ainsi chaque utilisateur exécute l’instruction d’administration.
Package com.contrastsecurity.test ;
public class TrojanSource {
public static void main(String[] args) {
String accessLevel = "user";
if (accessLevel != "useru202E u2066//Check if adminu2069 u2066") {
System.out.println("You are an admin.");
/* end admin only { */
}
}
}
Quelles sont les défenses existantes contre la source du cheval de Troie ?
La plupart des IDE restituent le code sous une forme en surbrillance syntaxique qui facilite la lisibilité. Ceux-ci n’affichent pas simplement du texte brut pour les voisins. Étant donné que les développeurs passent plusieurs heures par jour dans un environnement à code couleur et mesurent souvent les revues de code dans les WTF, le fait de voir du code mal coloré en amènera beaucoup à se poser une question équestre sur ce qui se passe.
De même, la plupart des analyseurs statiques détecteront et signaleront ce type de code, principalement parce qu’il est déroutant et difficile à lire.
GitHub – GitHub placera un avertissement sur les fichiers contenant des caractères de contrôle de texte bidirectionnel.
NetBeans – NetBeans interprète et code correctement par couleur les caractères de contrôle.
IntelliJ – IntelliJ interprète et code correctement par couleur les caractères de contrôle, mais code le commentaire de manière incorrecte – il est toujours clair que quelque chose ne va pas. Il affiche également une bannière en haut, indiquant qu’il y a du texte bidirectionnel.
Code contre – Visual Studio Code interprète et code correctement par couleur les caractères de contrôle
Éclipse – Eclipse interprète et code correctement par couleur les caractères de contrôle.
Comment la source du cheval de Troie interagit-elle avec les tests de sécurité des applications ?
La plupart des analyseurs de sécurité passeront simplement devant cette attaque, comprenant le code comme une machine plutôt que comme un être humain trompé.
Les outils de test de sécurité des applications courants incluent :
- Analyse de la composition au moment de la construction, pour localiser les dépendances vulnérables.
- Analyse statique au moment de la construction ou de la validation, pour localiser les vulnérabilités spécifiques au code.
- Analyse intégrée lors des tests, utilisant un agent dans l’application pour extraire le contexte de sécurité.
Il est peu probable que l’un de ces outils produise des résultats différents en fonction des tentatives de masquer le code avec cette attaque Trojan Source. Les outils d’analyse de composition ne seront absolument pas affectés car ils énumèrent simplement les dépendances pour localiser celles qui contiennent des CVE connus.
Les analyseurs statiques ne seront généralement pas dupes non plus. De nombreux analyseurs exploitent le bytecode en plus du code source, et ceux qui fonctionnent sur le code source analyseront le code avec une grammaire qui parcourt correctement les contrôles Unicode. Dans les captures d’écran ci-dessus, certains IDE citaient déjà des problèmes de qualité dans l’extrait Unicode.
Les analyseurs intégrés généreront toujours des résultats de sécurité complets à partir d’une application, car ils se concentrent sur le code qui s’exécute. En conséquence, les analyseurs produiront toujours une suite complète de résultats de sécurité pour détecter des problèmes tels que des défauts d’injection, une faible utilisation de la cryptographie ou d’autres types de défauts.
Quel est l’impact sur l’écosystème Java ?
Bien que des acteurs malveillants puissent soumettre des pull request avec des caractères de contrôle Unicode, ils sont relativement faciles à repérer.
Une autre défense de l’écosystème Java est la séparation du bytecode du code source et le fait que de nombreux outils (tels que les analyseurs statiques et intégrés) fonctionnent sur le bytecode. Ceci est dû au fait que les machines s’exécutent et que JIT compile le bytecode et souvent le code source n’est pas présent pour les bibliothèques. Une autre attaque consisterait simplement à fournir un morceau de code source mais à compiler un binaire différent avec des instructions supplémentaires.
Pour le Trojan Source, l’intention est clairement définie dans le bytecode. Tous les compilateurs Java pour n’importe quel JDK produiront une sortie identique ou extrêmement similaire car la connexion aux caractères Unicode est définie dans la spécification du langage Java, chapitre 3, section 3 : échappements Unicode.
Un outil distinct, javap, est distribué pour simplifier la capacité d’un développeur à consulter le bytecode. Le bytecode est une forme intermédiaire de code compilé qui est également destiné à être lu par les humains – en tant que tel, il peut être inspecté, décompilé, etc. Bien que la plupart des gens ne regardent pas réellement le bytecode et qu’il soit déraisonnable de s’attendre à ce que la plupart des gens le fassent, la distinction importante est que beaucoup ou la plupart des outils examinent le bytecode et verraient le résultat de toute tentative de Trojan Source.
Dans ce bytecode, nous voyons la première opération LDC (load constant) définir le mot « user » pour représenter le niveau d’accès. Le code 4 représente la chaîne complète qui est codée par couleur par les différents IDE, représentant la tentative de masquer le code (qui n’est pas masqué du bytecode). La comparaison IF_ACMPEQ sur le code 6 compare la constante de pile précédente « user » à cette autre chaîne « user //Check if admin » et si true passe au retour.
Avec l’utilisation courante des outils par la communauté Java, il est peu probable que les attaques de Trojan Source aient un impact notable sur les projets Java au-delà des contributions de code difficiles à lire mais malveillantes.
Les développeurs ont-ils désormais plus de responsabilités ?
Non. La plupart des équipes de développement veulent un code lisible et rejettent le code illisible. Très probablement, l’industrie signalera simplement les fichiers sources qui contiennent cette attaque, plus pour des raisons de lisibilité et cognitives que pour des raisons de sécurité. Les caractères peuvent être autorisés uniquement dans certains fichiers multilingues ou dans des lots de traduction pour des langues spécifiques plutôt que codés dans des fichiers.
Quel est le bon endroit pour réparer la source du cheval de Troie ?
Alors que le compilateur peut sembler être un emplacement efficace pour la défense, la faille est dans l’interprétation Unicode et aurait toujours un impact sur les analyseurs qui lisent d’autres types de données. Une bonne défense consiste à concentrer le travail de projet sur la lisibilité et à séparer le code des données. Une vieille citation de Donald Knuth s’applique, « Les programmes sont destinés à être lus par des humains et seulement accessoirement pour que les ordinateurs s’exécutent. »
- Rejetez le code qui contient des caractères d’encodage Unicode illisibles au motif qu’ils sont difficiles à lire et qu’ils auront un impact sur la maintenabilité du projet.
- Lorsque vous traitez des données traduites qui nécessitent un peu d’Unicode, placez ces données dans des fichiers de traduction séparés. Le séparer du code facilitera également la modification.