Skip to main content

Trojan-Source-Angriffe in JavaScript-Codebasen mit ESLint effektiv erkennen und entschärfen

Artikel von

10. November 2021

0 Min. Lesezeit

Am 1. November 2021 beschrieb die öffentliche Veröffentlichung einer Arbeit mit dem Titel Trojan Source: Unsichtbare Schwachstellen, wie Angreifer Unicode-Steuerzeichen für bidirektionalen Text einsetzen können, um schädlichen Quellcode in eine ansonsten unbedenkliche Codebasis einzuschleusen. Bei diesem Angriff werden Reviewer dazu gebracht, den verschleierten schädlichen Quellcode mit Kommentaren zu verwechseln.

Was ist ein Trojan-Source-Angriff?

Herkömmliche Code-Editoren und Code-Review-Verfahren erkennen keine bidirektionalen Zeichen im Quellcode. Dadurch können Angreifer schädlichen Code einschleusen, der harmlos aussieht. Diese Schwachstelle wurde am 1. November 2021 öffentlich gemacht und erhielt die Kennung CVE-2021-42574.

Das folgende Snippet aus VS Code zeigt einen Trojan-Source-Angriff in JavaScript-Quellcode:

// running internal logic for privileged users:
var accessLevel = "user";
if (accessLevel != "user‮ ⁦// Check if admin⁩ ⁦") {
    console.log("You are an admin.");
}

Und wie sieht es jetzt mit diesem Screenshot aus:

JavaScript-Codeausschnitt, der prüft, ob accessLevel ungleich „user“ ist, und eine Admin-Nachricht protokolliert

Haben Sie das Problem im obigen Quellcode entdeckt? Falls nicht, sehen Sie sich das Code-Snippet noch einmal genauer an.

Was hier passiert: Es handelt sich um einen Angriff vom Typ Stretched String. Der Code in Zeile 3 erweckt den Eindruck, als prüfe der bedingte Ausdruck, ob die Variable accessLevel dem Wert user entspricht. Am Ende der Zeile steht ein Kommentar zu Logikprüfungen, der harmlos wirken mag. Tatsächlich sieht es jedoch ganz anders aus.

Tatsächlich wird der echte Zeichenfolgenwert der Prüfung der Variable accessLevel durch bidirektionale Unicode-Zeichen in Zeile 3 verschleiert. So sieht die tatsächliche Zeile 3 aus, die der Compiler ausführt:

If (accessLevel != "user // Check if admin") {

Die Arbeit beschreibt verschiedene Arten, bidirektionale Steuerzeichen zu missbrauchen, um schädlichen Code in Quellcode einzuschleusen: Commenting-Out, Stretched String, Invisible Functions und Homoglyph Function. Die Forschenden haben JavaScript-Beispiele für alle diese Angriffe bereitgestellt, die über dieses trojan-source-Repository auf GitHub ausgeführt werden.

Der Einsatz bidirektionaler Steuerzeichen ist zwar neu, aber diese Art von Angriff ist nicht wirklich neu und wurde bereits in früheren Mailinglisten und Diskussionsforen erwähnt. Beispiele dafür sind dieser Golang-Issue aus dem Jahr 2017 zum Verbot von RTL-/LTR-Zeichen oder dieser Bugzilla-Eintrag aus dem Jahr 2011 mit dem Titel [BiDi] Irreführende Darstellung bidirektionaler Zeichenfolgen bei Verwendung von RLO, LRO oder PDF (Hinweis: Der Eintrag ist über Google Cache zugänglich).

Wie können Sie Trojan-Source-Angriffe beheben?

Die Autoren der wissenschaftlichen Arbeit sind der Ansicht, dass das Problem bei Code-Editoren und IDE-Software liegt. Diese sollten so angepasst werden, dass solche Unicode-Zeichen visuell sichtbar sind. Compiler sollten Nutzer außerdem davor warnen.

Trojan-Source-Angriffe im Quellcode erkennen

Ihre Codebearbeitungs- und Code-Review-Prozesse finden möglicherweise auf Plattformen oder mit Tools statt, die diese gefährlichen bidirektionalen Unicode-Zeichen nicht hervorheben können. Das bedeutet, dass sich solche bidirektionalen Zeichen möglicherweise bereits in Ihrer Codebasis befinden.

Wie finden Sie also heraus, ob Ihr Quellcode bidirektionale Unicode-Zeichen enthält? Dafür habe ich ein npm-Paket namens anti-trojan-source entwickelt. Es scannt ein Verzeichnis oder liest Eingaben über die Standardeingabe (STDIN) ein und sucht im Text nach solchen Unicode-Zeichen.

Mit npx können Sie Dateien wie folgt scannen:

npx anti-trojan-source --files='src/**/*.js'

Oder Sie verwenden das Paket als Bibliothek in einem JavaScript-Projekt:

import { hasTrojanSource } from 'anti-trojan-source'
const isDangerous = hasTrojanSource({
  sourceText: 'if (accessLevel != "user) {' // Check if admin
})

Trojan-Source-Angriffe in JavaScript mit ESLint verhindern

Hinweis der Redaktion: Seit der Erstveröffentlichung dieses Beitrags wurden Trojan-Source-Regeln zu Snyk Code hinzugefügt. Erfahren Sie mehr in unserem Blogbeitrag So verhindern Sie Trojan-Source-Angriffe mit Snyk Code.

Noch besser, als vorhandene Probleme nur aufzuspüren, ist es, Ihre Codebasis proaktiv abzusichern und so zu verhindern, dass Trojan-Source-Angriffe überhaupt in Ihren Quellcode gelangen. In der JavaScript-Community verlassen wir uns häufig auf ESLint und seine verschiedenen Plugins, um Standards für Codequalität und Codestil durchzusetzen.

Mit eslint-plugin-anti-trojan-source können Sie jetzt auch ein ESLint-Plugin einbinden, das sicherstellt, dass weder Ihre Entwickler noch Ihre CI- und Build-Systeme versehentlich Code zusammenführen, der durch bidirektionale Unicode-Zeichen potenziell schädlich ist.

Hier sehen Sie eine Beispielkonfiguration für ESLint in einem JavaScript-Projekt:

"eslintConfig": {
    "plugins": [
        "anti-trojan-source"
    ],
    "rules": {
        "anti-trojan-source/no-bidi": "error"
    }
}

Und hier eine Beispielausgabe für ein anfälliges Code-Snippet, das in die Codebasis gelangt ist:

$ npm run lint

/Users/lirantal/projects/repos/@gigsboat/cli/index.js
  1:1  error  Detected potential trojan source attack with unicode bidi introduced in this comment: ' begin admins only '  anti-trojan-source/no-bidi if (isAdmin) {
  1:1  error  Detected potential trojan source attack with unicode bidi introduced in this comment: ' end admin only    anti-trojan-source/no-bidi }

/Users/lirantal/projects/repos/@gigsboat/cli/lib/helper.js
  2:1  error  Detected potential trojan source attack with unicode bidi introduced in this code: '"user" // Check if admin

Wie geht das Ökosystem gegen Trojan-Source-Angriffe vor?

IDEs wie VS Code haben Versionen veröffentlicht, die diese Unicode-Zeichen hervorheben, damit Programmierer darauf aufmerksam werden und beim Prüfen und Bearbeiten von Code den richtigen Kontext berücksichtigen. Ebenso hat GitHub Warnungen veröffentlicht, sodass visuell dargestellte Codebasen nun die Verwendung dieser potenziell gefährlichen Trojaner auf GitHub hervorheben, wenn bidirektionale Zeichen darin vorkommen:

GitHub-Codeansicht mit Warnung, dass die JavaScript-Datei bidirektionalen Unicode-Text enthält, und einer Bedingung, die prüft, ob es sich um einen Admin-Benutzer handelt.
Quelle: https://github.com/nickboucher/trojan-source/blob/main/JavaScript/stretched-string.js

Beachten Sie jedoch, dass GitHub nicht alle Arten von Trojaner-Malware-Angriffen hervorhebt. Betrachten Sie beispielsweise den folgenden Fall, den die Arbeit beschreibt und als Invisible Functions bezeichnet:

Code-Editor mit zwei ähnlich benannten isAdmin-Funktionen, die false bzw. true zurückgeben, gefolgt von einer Bedingung für den Admin-Zugriff.

Wie Sie im obigen JavaScript-Code-Snippet sehen, zeigt GitHub beim Prüfen dieses Codes keine Warnungen an. Was passiert hier tatsächlich?

Die Funktionsdeklaration in Zeile 7 enthält tatsächlich ein Unicode-Steuerzeichen für ein Leerzeichen der Breite null, gekennzeichnet als U200B. Dadurch sieht sie optisch wie eine legitime Funktion function isAdmin() aus.

Wir können das überprüfen, indem wir den Code mit einem Tool wie bat ausgeben. Dabei handelt es sich um einen Klon des UNIX-cat-Tools mit besserer Syntaxhervorhebung und Git-Integration:

JavaScript-Code mit optisch ähnlichen Funktionsnamen, die unsichtbare Unicode-Zeichen verwenden. Eine Funktion gibt false zurück, die andere true.

Sollten Compiler und Laufzeitumgebungen Trojan-Source-Angriffe abwehren?

Wie sieht es bei Compilern und Sprachlaufzeitumgebungen aus? Die meisten Sprachen, einschließlich Node.js, haben sich dagegen entschieden, ihre Compiler so zu aktualisieren, dass sie Unicode-Zeichen zurückweisen. Dadurch wird das Risiko im Wesentlichen auf Code-Editoren und Menschen verlagert, die beim Lesen von Code und bei Code-Reviews besonders sorgfältig sein müssen.

Einige Sprachlaufzeiten wie Zig haben dagegen in Erwägung gezogen, bei der Erkennung bidirektionaler Unicode-Zeichen im Quellcode einen Compilerfehler auszugeben und das Umgehen dieser Fehler durch einen expliziten Kommentar zu ermöglichen.

Ressourcen zu Trojan-Source-Angriffen

Ich hoffe, dieser Beitrag hat Ihnen geholfen, Trojan-Source-Angriffe und ihre möglichen Auswirkungen auf das JavaScript-Ökosystem zu verstehen. Wenn Sie mehr über diese Angriffe erfahren möchten, empfehle ich Ihnen die folgenden Ressourcen:

  1. Blogbeitrag: So verhindern Sie Trojan-Source-Angriffe mit Snyk Code

  2. Die offizielle Website zu Trojan Source: https://www.trojansource.codes

  3. Das offizielle Trojan-Source-Repository mit Codebeispielen und Proofs of Concept: https://github.com/nickboucher/trojan-source

  4. Der offizielle Ankündigungs-Blogbeitrag zu Trojan Source:  https://www.lightbluetouchpaper.org/2021/11/01/trojan-source-invisible-vulnerabilities

Sichern Sie Ihren Code mit modernsten Erkenntnissen

Lernen Sie in nur 30 Minuten das gesamte Funktionsspektrum von Snyk Code SAST kennen.

Weiterlesen

Blog

Frontier-Modelle fanden die Schwachstellen. Nur der Angreifer fand die Angriffsketten.

Die statische Analyse fand die Schwachstellen, doch erst Live-Angriffstests bewiesen, wie sie sich zu Angriffen verketten lassen. Ein Vergleich von Evo COS, Claude Security und Claude Code Security.

feature insights context
Blog

Autonome Angriffe sind bereits Realität. Die Verteidigung muss Schritt halten.

Autonome Angreifer verkürzen das Zeitfenster für die Verteidigung. Erfahren Sie, wie kontinuierliches Erkennen, Beheben, Validieren und Verhindern Sicherheitsteams helfen kann, Schritt zu halten.

Blog

Warum KI-Coding-Agenten immer wieder fehlerhafte Zugriffskontrollen schreiben

KI-Coding-Agenten können Autorisierungslogik erzeugen, die kompiliert und die Prüfung besteht, dabei aber die Daten eines Mandanten für einen anderen offenlegt. Erfahren Sie, warum fehlerhafte Zugriffskontrollen schwer zu erkennen sind und wie Sie sie verhindern.