Skip to main content

So verhindern Sie Log-Injection-Schwachstellen in JavaScript- und Node.js-Anwendungen

Artikel von
feature open source

26. September 2024

0 Min. Lesezeit

In vielen gängigen Unternehmensanwendungen erfüllt eine konsistente Protokollierung zahlreiche Zwecke. Sie hilft Unternehmen, Fehler zu erkennen und zu beheben, liefert wertvolle analytische Erkenntnisse und ermöglicht es, neue Lösungen zu testen. Gleichzeitig zählen Log-Injections dadurch zu den häufigsten Methoden, mit denen Hacker Anwendungen kapern oder sogar auf sensible Nutzerinformationen zugreifen können. Schwachstellen in der Art und Weise, wie Anwendungen Daten protokollieren, können es Angreifern ermöglichen, schädlichen Code in Logs einzuschleusen und so die Integrität und Vertraulichkeit Ihrer Anwendung zu gefährden.

In diesem Artikel geht es speziell um Log-Injection-Schwachstellen in Node.js. Sie erfahren, wie Log-Injections funktionieren und wie Sie sie wirksam verhindern können.

Was ist eine Log-Injection-Schwachstelle?

Manche Anwendungen schreiben Protokollinformationen in eine externe Datei oder nutzen eine externe API, an die Logs gesendet werden. Bei einer Log-Injection manipuliert ein Angreifer Eingabedaten, um schädlichen Code in die Logs der Anwendung einzuschleusen. Diese Logs dienen in der Regel dem Debugging, der Überwachung und der Auditierung.

Bei einer Log-Injection kann der Angreifer die Logs mit Einträgen überfluten oder sogar Code im Kontext der Anwendung ausführen, was verschiedene Sicherheitsrisiken mit sich bringt.

Beispiel für eine anfällige Node.js-App

Stellen Sie sich eine einfache Node.js-Anwendung vor, die das Express-Webframework verwendet und von Nutzern eingegebene Daten ohne angemessene Validierung oder Bereinigung protokolliert. Das folgende Code-Snippet veranschaulicht diese Schwachstelle:

const express = require('express');
const app = express();

app.get('/log', (req, res) => {
  const userInput = req.query.data;
  console.log('INFO: ' + userInput);
  res.send('Data logged successfully.');
});

app.listen(3000, () => {
  console.log('Server started on port 3000');
});

Sobald dieser Server lokal läuft, können Sie mit API-Testtools wie Insomnia eine GET-Anfrage senden und prüfen, ob alles wie erwartet funktioniert. In diesem Fall möchten Sie einen Nutzernamen aus einem Formular protokollieren, um zu testen, wie die Server-Logs aussehen. Sie fügen die Daten im erwarteten Format hinzu und senden die Anfrage. Daraufhin erhalten Sie den Status 200 OK und die Meldung „Data logged successfully.“:

API-Client mit einer POST-Anfrage zum Protokollieren von Daten und der erfolgreichen Antwort „Daten erfolgreich protokolliert“

Wenn Sie die Logs auf der Serverseite prüfen, sieht alles wie erwartet aus. Da Sie den Wert charlie zu den Datenparametern hinzugefügt haben, zeigt das Log den Eintrag INFO: charlie auf dem Server:

Terminal mit einem Node.js-Express-Server, der auf Port 3000 gestartet wurde, und einem INFO-Protokolleintrag mit dem Text „charlie“

Eine Möglichkeit, die Protokollierung dieser Anwendung zu missbrauchen, besteht darin, über den Parameter data gefälschte Log-Einträge einzuschleusen. In diesem Beispiel müsste ein Angreifer lediglich zusätzlichen Text an die Abfrage anhängen:

API-Client mit einer GET-Anfrage an localhost, die eine kodierte Log-Injection-Payload und eine erfolgreiche 200-Antwort zeigt.
Terminal mit einem Node.js-Express-Server, der auf Port 3000 startet und die Löschung eines Benutzers protokolliert

Ein Angreifer könnte beispielsweise INFO: User deleted als gefälschten Log-Eintrag hinzufügen. Wenn das Entwicklungsteam diesen Eintrag entdeckt, könnte es in die Irre geführt werden und Zeit und Ressourcen darauf verwenden, herauszufinden, warum die Anwendung Nutzer löscht, wenn jemand einen Nutzernamen eingibt – nur weil ein Angreifer zusätzliche Zeichen in ein Eingabefeld eingeschleust hat.

Dieses Beispiel ist zwar einfach gehalten, hilft Ihnen aber, Log-Injections allgemein zu verstehen. Andere Arten von Injections können gefälschte Fehler- oder Nutzerinformationen in Logs einschleusen, indem die Log-Nachricht verändert wird. Noch schlimmer sind Befehlsinjektionen, die Angreifern direkten Zugriff auf interne Daten ermöglichen.

So verhindern Sie Log-Injection-Schwachstellen in Node.js

Um Log-Injection-Schwachstellen in Ihren Node.js-Anwendungen zu entschärfen, sollten Sie einige dieser bewährten Maßnahmen umsetzen:

Nutzereingaben bereinigen

In den meisten Fällen sollten Nutzereingaben vor der Protokollierung validiert und bereinigt werden. Das bedeutet, dass Sie alle zu protokollierenden Daten sorgfältig prüfen, um Zeichen auszuschließen, die mit einer anderen Log-Eingabe verwechselt werden könnten, und/oder nur Zeichen zuzulassen, die in den Logs vorkommen dürfen.

Im vorherigen Beispiel könnten Sie Logs bereinigen, indem Sie einen regulären Ausdruck verwenden, der ausschließlich Buchstaben zulässt. So verhindern Sie, dass Sonderzeichen oder Zahlen in das Log gelangen:

app.get('/log', (req, res) => {
  const userInput = req.query.data
  const sanitizedInput = userInput.replace(/[^a-zA-Z]+/, '')
  console.log('INFO: Username: ', sanitizedInput);
  res.send('Data logged successfully.');
});
Terminal mit einem Node.js-Express-Serverprotokoll, das einen Benutzernamen-Eintrag und die Meldung „INFO: User deleted“ zeigt

Beachten Sie dabei, dass es schwierig sein kann, die richtige Methode zur Datenbereinigung auszuwählen. In diesem Beispiel würde der Nutzername im Log verändert, wenn er Zahlen enthält (z. B. 123).

Die Bereinigung von Eingaben kann zwar helfen, schädliche Log-Einträge abzufangen, doch müssen Entwickler sorgfältig abwägen, welche Zeichen sie herausfiltern und wie sie dabei vorgehen. Falsch formulierte reguläre Ausdrücke können beispielsweise zu ReDoS-Schwachstellen führen, die Node.js-Anwendungen vollständig lahmlegen. Drittanbieter-npm-Pakete wie validator.js sind eine gute Möglichkeit, das Rad nicht neu zu erfinden. Achten Sie jedoch darauf, diese Abhängigkeiten stets aktuell zu halten.

Protokollieren Sie mit Bedacht

Jede Anwendung ist einzigartig. Ein einzelner Protokollierungsstandard kann nicht alle potenziellen Anforderungen jeder Anwendung abdecken. Daher sollten Sie genau überlegen, welche Informationen Sie protokollieren müssen und für wen.

Logs auf DEBUG-Ebene helfen Entwicklern dabei, nachzuvollziehen, was in einer Anwendung geschieht, wie Nutzer von einer Komponente zur nächsten navigieren und wie Informationen von einer Quelle zur anderen fließen. Logs auf WARN- oder ERROR-Ebene helfen Entwicklungsteams, potenzielle Fehler frühzeitig zu erkennen und zu verstehen, warum eine Anwendung abstürzt oder nicht ordnungsgemäß funktioniert. Entscheidend ist, nur das Nötige zu protokollieren und nichts darüber hinaus. Bedenken Sie dabei auch, was passieren könnte, wenn Angreifer Zugriff auf Ihre Logs erhalten.

Wie dieser Snyk-Artikel über Schwachstellen bei der Protokollierung erläutert, können sensible Informationen, die an einen externen Protokollierungsdienst gesendet werden, von Angreifern abgegriffen werden. Generell sollten Sie sensible oder vertrauliche Informationen wie Passwörter, API-Schlüssel oder personenbezogene Daten nicht protokollieren. Falls Sie es doch tun, sorgen Sie für geeignete Zugriffskontrollen und erwägen Sie, Umgebungsvariablen (etwa in GitHub Actions) und Schlüsselverwaltungssysteme zu verwenden, um sensible Konfigurationsdaten sicher zu verwalten.

Neben der Frage, was Sie protokollieren, sollten Sie auch überlegen, wie Sie es tun. Strukturierte Protokollierung bietet eine übersichtlichere Möglichkeit, Daten zu protokollieren, die Entwickler leichter auswerten können. Im vorherigen Beispiel könnten Sie die Nutzerdaten beispielsweise nicht direkt als Zeichenfolge protokollieren, sondern ein JSON-Objekt verwenden, um die protokollierten Inhalte übersichtlich zu kennzeichnen:

app.get('/log', (req, res) => {
  const userInput = req.query.data;
  const log = {username: userInput, 'action':'submitted username', 'time': new Date()}
  console.log(log)
  res.send('Data logged successfully.');
});

Noch wichtiger: Eine solche Strukturierung kann es Angreifern erschweren, Log-Einträge einzuschleusen, da sie dafür mehrere Eigenschaften des Log-Objekts manipulieren müssten (z. B. action oder time). Tun sie das nicht, kann ihr Vorgehen auffliegen:

Terminalausgabe mit einem Node.js-Express-Server auf Port 3000 und einem protokollierten Vornamen, der eine eingeschleuste Nachricht mit Zeilenumbruch enthält

Die Protokollierung eines JSON-Objekts ist zwar ein einfaches Beispiel, doch es gibt Logging-Bibliotheken (auf die wir als Nächstes eingehen), die strukturierte Protokollierung als hilfreiche Alternative zum üblichen console.log anbieten.

Verwenden Sie eine Logging-Bibliothek statt console.log

Viele Logging-Bibliotheken bieten im Vergleich zu console.log mehr Kontrolle und Sicherheit bei der Ausgabe von Logs, da sie in der Regel integrierte Funktionen zur Bereinigung und Filterung enthalten, die Log-Injection-Angriffe verhindern. Außerdem ermöglichen sie Entwicklern, über Flags festzulegen, welche Logs in welcher Umgebung (Test oder Produktion) angezeigt werden, flexibel zu bestimmen, wohin Logs gesendet werden (lokale Datei, Datenbank und/oder Drittanbieter-API) und die Protokollierung so zu konfigurieren, dass sich Logs leichter zurückverfolgen lassen.

Eine von uns empfohlene Bibliothek ist pino. Sie wird gut gepflegt und ist insgesamt ein zuverlässiges Paket ohne bekannte Sicherheitslücken.

Pino ist auf hohe Leistung optimiert und lässt sich so konfigurieren, dass jeder Log-Eintrag einen Zeitstempel enthält. Die Bibliothek unterstützt strukturierte Protokollierung und standardisierte System-Log-Level. Diese zusätzliche Komplexität und Struktur kann die Sicherheit erhöhen und es Angreifern erschweren, Logs zu kompromittieren.

Erkennen Sie Schwachstellen mit der Snyk-IDE-Erweiterung für VS Code

Snyk bietet eine kostenlose IDE-Erweiterung für Visual Studio Code (VS Code), mit der Sie Log-Injection-Schwachstellen und andere Schwachstellen in Ihrem Node.js-Code erkennen können. So richten Sie sie ein:

Öffnen Sie in VS Code die Registerkarte Extensions und suchen Sie nach „Snyk“, um die Erweiterung „Snyk Security - Code, Open Source Dependencies, Iac Configurations“ zu finden. Klicken Sie auf Install:

Marketplace für Visual Studio Code-Erweiterungen mit dem Eintrag der Snyk Security-Erweiterung und einer Schaltfläche „Installieren“

Nach der Installation fordert Snyk Sie auf, Ihr Konto zu authentifizieren, indem Sie es mit Ihrer IDE verbinden. Klicken Sie auf Connect VS Code with Snyk. Daraufhin öffnet sich eine externe Snyk-Webseite, auf der Sie der Verbindung zustimmen können. Klicken Sie dort auf Authenticate.

Klicken Sie nach der Authentifizierung auf Scan, um Ihren Code auf Schwachstellen zu prüfen. Sie können die Erweiterung außerdem nach Bedarf konfigurieren:

Snyk Code-Sicherheitspanel in einem Code-Editor mit sechs Schwachstellen und 55 Codequalitätsproblemen in JavaScript-Dateien

Die Snyk-IDE-Erweiterung scannt Ihren Code automatisch auf Log-Injection-Schwachstellen. Außerdem weist Snyk Sie während des Scans auf weitere potenzielle Sicherheitsprobleme hin, etwa fest codierte Geheimnisse oder Path-Traversal-Schwachstellen, und liefert konkrete Einblicke und Empfehlungen, die Ihnen dabei helfen, Ihre Anwendung abzusichern.

Starten Sie kostenlos mit Snyk

Keine Kreditkarte erforderlich.

Konto mit Bitbucket und weiteren Optionen erstellen

Mit der Nutzung von Snyk erklären Sie sich mit unseren Richtlinien einverstanden, einschließlich unserer Nutzungsbedingungen und unserer Datenschutzerklärung.

Weiterlesen

illustration hero ai
Blog

PHP behebt zwei kritische unauthentifizierte RCE-Schwachstellen (CVE-2026-109618, CVE-2026-109619): Jetzt aktualisieren

Zwei kritische Sicherheitslücken im Request-Lebenszyklus von PHP können unauthentifizierte Remote Code Execution ermöglichen. Aktualisieren Sie auf eine korrigierte Version oder installieren Sie für ältere Versionen einen Backport des Anbieters.

blog feature ai lilac
Blog

Mit agentischer Behebung Ihren Schwachstellen-Backlog in Pull Requests verwandeln

Der Evo Remediation Agent ist jetzt in der öffentlichen Vorschau verfügbar und erweitert Evo Agentic AppSec um die automatisierte Auflösung von Abhängigkeiten. AppSec-Teams können jetzt kontinuierliche Behebungskampagnen durchführen

AI Background min crop
Blog

KI ruft alle Risiken auf den Plan, die Sie akzeptiert haben: Sieben Erkenntnisse aus dem AI Security Panel: Unfiltered

KI macht Angriffe günstiger und schneller und legt Risiken offen, die Unternehmen bereits tragen. Vier Sicherheitsverantwortliche erklären, warum Abwehr in Maschinengeschwindigkeit und schnellere Behebung jetzt unverzichtbar sind.