DOM-Clobbering-Angriffe in JavaScript eindämmen
Keshav Malik
7. August 2023
0 Min. LesezeitDas Document Object Model (DOM) dient als Schnittstelle zwischen HTML und JavaScript und überbrückt die Kluft zwischen statischen Inhalten und dynamischer Interaktivität. Dadurch ist das DOM für moderne Webentwickler unverzichtbar.
Das DOM birgt jedoch eine Tücke: DOM-Clobbering. DOM-Clobbering tritt auf, wenn HTML-Elemente mit globalen JavaScript-Variablen oder -Funktionen in Konflikt geraten. Das kann zu unerwartetem Verhalten und einer potenziellen Sicherheitslücke in Ihrer Webanwendung führen.
Um dieses Problem zu beheben, sind sorgfältige Programmierpraktiken, fundierte JavaScript-Kenntnisse und ein solides Verständnis der Sicherheit von Webanwendungen erforderlich. Dieser Artikel erläutert das Konzept des DOM-Clobberings und zeigt Strategien für sicherere und robustere Webanwendungen.
Wie DOM-Clobbering entsteht
Jedes HTML-Element kann ein eindeutiges ID- oder name-Attribut haben, damit sich bestimmte Elemente in JavaScript leicht referenzieren lassen. Die folgende HTML-Schaltfläche hat beispielsweise ein ID-Attribut mit dem Wert "myButton":
Mit dieser ID können wir die Schaltfläche in unserem JavaScript-Code bearbeiten, indem wir beispielsweise ihren Text ändern, wenn darauf geklickt wird:
Das DOM ermöglicht diese Interaktion zwischen HTML und JavaScript. Was passiert jedoch, wenn das ID- oder name-Attribut des HTML-Elements mit einer globalen JavaScript-Variablen oder -Funktion in Konflikt steht?
Wenn ein Browser eine HTML-Seite lädt, erstellt er automatisch globale JavaScript-Variablen für jedes ID- und name-Attribut im HTML-DOM. Gibt es ein HTML-Element mit dem Namen "myButton", erstellt der Browser die globale JavaScript-Variable myButton, die auf dieses HTML-Element verweist.
Sehen wir uns nun ein Szenario an, in dem wir eine JavaScript-Funktion namens myButton deklariert haben:
Zusätzlich gibt es ein HTML-Element mit der ID oder dem Namen "myButton". Beim Laden der Seite überschreibt der automatische Prozess des Browsers die JavaScript-Funktion myButton mit einer Referenz auf das HTML-Element:
Dieser Vorgang wird als DOM-Clobbering bezeichnet und kann unvorhersehbares Verhalten sowie Sicherheitslücken verursachen. Kann ein Angreifer die Attribute kontrollieren, kann er möglicherweise bösartigen Code in die Webseite einschleusen. Das kann zu Sicherheitsproblemen wie Cross-Site-Scripting (XSS) führen.
Zur Veranschaulichung betrachten wir das folgende Szenario:
Ein Angreifer könnte etwa <img id='alert' src=x onerror='alert(1)'> eingeben und so eine neue HTML-Komponente mit der 'id' 'alert' erstellen. Diese Komponente ersetzt – oder überschreibt – die normale JavaScript-Funktion alert. Wenn die Website diese Funktion das nächste Mal aufruft, funktioniert sie nicht ordnungsgemäß und könnte sogar bösartigen Code ausführen.
DOM-Clobbering-Sicherheitslücken erkennen
Betrachten wir eine einfache Webanwendung mit einem Feedback-Formular. Nutzer geben ihren Namen und eine Feedback-Nachricht ein und senden das Formular ab. Die Seite zeigt das Feedback an:
HTML:
JavaScript:
Dieser Code nimmt den Namen und das Feedback des Nutzers und zeigt beides in einem Absatzelement innerhalb des feedbackDisplay-Divs an.
Ein Angreifer könnte diesen Code ausnutzen, indem er HTML über das Feedback-Formular übermittelt. Gibt er beispielsweise den folgenden Code in das Feld Name ein und sendet das Formular ab, wird der Feedback-Anzeigebereich durch das script-Tag ersetzt:
Wenn das Formular versucht, das nächste Feedback anzuzeigen, wird stattdessen das Script ausgeführt und der Nutzer auf eine bösartige Website umgeleitet.
Dieses Szenario stellt eine Sicherheitslücke dar, weil die Anwendung vom Nutzer bereitgestellte Eingaben zur Erstellung von HTML verwendet und dabei ein script-Tag mit derselben ID wie ein vorhandenes Element erzeugt. Dies ist ein Beispiel für DOM-Clobbering mit schwerwiegenden Folgen: Der Angreifer kann die Kontrolle über den Browser des Nutzers erlangen und dadurch vertrauliche Daten stehlen oder Malware installieren.
Sichere Programmierpraktiken zur Vermeidung von DOM-Clobbering
Nachdem wir diese Sicherheitslücken genauer betrachtet haben, sehen wir uns einige Best Practices an, mit denen sich das Risiko von DOM-Clobbering verringern lässt.
Variablen und Funktionen korrekt im Gültigkeitsbereich einschränken
Eine der häufigsten Ursachen für DOM-Clobbering ist der unsachgemäße Umgang mit dem globalen Gültigkeitsbereich in JavaScript. Wenn wir Variablen und Funktionen innerhalb eines bestimmten Gültigkeitsbereichs definieren, können wir das Überschreiben auf diesen Bereich und darin verschachtelte Bereiche beschränken und so potenzielle Konflikte minimieren.
Wenden wir die Gültigkeitsbereichsregeln von JavaScript an und strukturieren wir das vorherige Beispiel um, um zu zeigen, wie das funktioniert:
Hinweis: Im obigen Codebeispiel haben wir DOMPurify verwendet, um das HTML zu bereinigen. Sie können es in Node.js mit npm install dompurify installieren. Binden Sie es mit <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.3.3/purify.min.js"></script> in Ihr HTML ein.
In dieser Codeversion haben wir alles in eine Immediately Invoked Function Expression (IIFE) eingeschlossen, die einen neuen Gültigkeitsbereich erstellt. Die Variablen form und feedbackElement sowie die dem Event-Handler onsubmit zugewiesene Funktion befinden sich nicht im globalen Gültigkeitsbereich und können daher nicht überschrieben werden.
Eindeutige Bezeichner verwenden
Wenn jedes Element auf unserer Webseite eine eindeutige ID hat, sinkt das Risiko, versehentlich eine wichtige Funktion oder Variable zu überschreiben. Vermeiden Sie außerdem gängige Namen oder Namen, die mit globalen JavaScript-Objekten oder -Funktionen in Konflikt geraten könnten.
Globale Namensraumverschmutzung vermeiden
Ein sauberer globaler Namensraum ist ein wichtiger Aspekt sicherer JavaScript-Programmierung. Je mehr Variablen und Funktionen sich im globalen Gültigkeitsbereich befinden, desto größer ist das Risiko für DOM-Clobbering. Nutzen Sie den Funktions-Gültigkeitsbereich von JavaScript oder den Block-Gültigkeitsbereich von ES6, um Variablen und Funktionen einzuschließen. Hier ein Beispiel mit Letzterem:
In diesem Code haben wir mit einem Block (definiert durch {}) einen neuen Gültigkeitsbereich erstellt. Alle Variablen und Funktionen sind jetzt auf diesen Block beschränkt und befinden sich nicht im globalen Gültigkeitsbereich.
Hinweis: Die Codebeispiele in diesem Leitfaden sind zu Demonstrationszwecken vereinfacht und nicht für den Einsatz auf einer Produktionswebsite oder in einer Produktions-App gedacht.
JavaScript-Funktionen zur Eindämmung von DOM-Clobbering nutzen
Modernes JavaScript bietet mehrere Funktionen, mit denen sich das Risiko von DOM-Clobbering verringern lässt. Insbesondere die in ES6 eingeführten Schlüsselwörter let und const bieten mehr Kontrolle bei der Deklaration von Variablen.
Traditionell haben wir JavaScript-Variablen mit dem Schlüsselwort var deklariert. var hat jedoch einige Eigenheiten. Eine davon ist, dass es keinen Block-Gültigkeitsbereich gibt – nur einen Funktions- und einen globalen Gültigkeitsbereich. Das bedeutet, dass auf eine mit var deklarierte Variable auch außerhalb des Blocks zugegriffen werden kann, in dem sie deklariert wurde, und dass sie dort überschrieben werden kann.
let und const haben dagegen beide einen Block-Gültigkeitsbereich. Das bedeutet, dass auf sie nur innerhalb des Blocks zugegriffen werden kann, in dem sie deklariert wurden. Deshalb eignen sie sich häufig besser für Variablendeklarationen, da sie die Möglichkeit verringern, dass Variablen überschrieben werden.
Mit const können wir außerdem Konstanten deklarieren – Werte, die sich nach ihrer Zuweisung nicht mehr ändern lassen. Sie sind ein weiteres nützliches Mittel, um unbeabsichtigte Änderungen an wichtigen Variablen zu verhindern.
Sehen wir uns an, wie wir diese Funktionen in unserem Feedback-Formularcode implementieren können, um DOM-Clobbering zu verhindern:
In diesem Code haben wir alle Vorkommen von var durch const ersetzt. Wir haben alle Variablen auf den Block beschränkt, in dem wir sie deklariert haben, und die Konstanten können nicht überschrieben werden.
Denken Sie daran: Die Verwendung von let und const beseitigt das Risiko von DOM-Clobbering nicht, ist aber dennoch ein entscheidender Bestandteil sicherer Programmierung. Wenn Sie diese JavaScript-Funktionen verstehen und einsetzen, können Sie Ihre Webanwendungen sicherer machen.
DOM-Clobbering-Sicherheitslücken überwachen und erkennen
Sichere Programmierpraktiken können DOM-Clobbering verhindern. Ebenso wichtig ist es jedoch, Sicherheitslücken zu erkennen, sobald sie auftreten. Sehen wir uns einige hilfreiche Tools und Techniken an.
Statische Codeanalyse
Tools für statische Anwendungssicherheitstests (SAST) wie Snyk Code können potenzielle Sicherheitslücken, darunter auch DOM-Clobbering, wirksam erkennen. Diese Tools analysieren Ihren Quellcode, ohne ihn auszuführen, und identifizieren Muster, die zu Sicherheitsproblemen führen könnten. Dank der umfassenden JavaScript-Abdeckung von Snyk ist das Tool eine ausgezeichnete Wahl für Webentwickler.
Browser-Entwicklertools
Browser-Entwicklertools, wie sie in Chrome oder Firefox verfügbar sind, können bei der Erkennung von DOM-Clobbering-Sicherheitslücken eine wertvolle Unterstützung sein.
Sehen wir uns kurz an, wie Sie mit diesen Tools ein potenzielles Problem erkennen können:
Klicken Sie auf Ihrer Webseite mit der rechten Maustaste auf eine beliebige Stelle und wählen Sie Untersuchen, um die Entwicklertools zu öffnen. Unter Windows können Sie auch Strg+Umschalt+I oder unter macOS Befehlstaste+Optionstaste+I drücken.
Wechseln Sie zum Tab Konsole, in dem JavaScript-Fehler und Protokollmeldungen angezeigt werden.
Geben Sie in der Konsole „window“ ein und drücken Sie Enter, um den globalen Gültigkeitsbereich mit allen globalen Variablen und Funktionen zu untersuchen. Achten Sie auf Variablen, die fehl am Platz wirken, insbesondere auf solche, deren Name mit der ID oder dem Namen eines HTML-Elements übereinstimmt.
Bearbeiten Sie im Tab Elemente das HTML der Seite, um das DOM zu verändern und auf potenzielle Sicherheitslücken zu testen. Fügen Sie beispielsweise ein Element mit einer ID hinzu, die mit einer globalen Variablen oder Funktion übereinstimmt, und prüfen Sie, ob diese überschrieben wird.
Fazit
Dieser Artikel hat erläutert, wie DOM-Clobbering entsteht, welche Gefahren damit verbunden sind und wie Sie sich davor schützen können. Die Variablen korrekt im Gültigkeitsbereich einzuschränken, eindeutige Bezeichner zu verwenden und die JavaScript-Funktionen let und const gezielt einzusetzen, ist entscheidend, um diese Sicherheitslücke einzudämmen.
Für die Sicherheit des Codes müssen Präventions- und Erkennungsmaßnahmen ausgewogen eingesetzt werden. Mit empfohlenen Programmierpraktiken, Browser-Entwicklertools und einer SAST-Lösung wie Snyk können bestehende und potenzielle Probleme erkannt werden.
Wenn Sie diese Techniken in Ihre JavaScript-Anwendungen integrieren und sich über aktuelle Trends bei der Sicherheit von Webanwendungen informieren, können Sie Ihre Programmierpraktiken proaktiv absichern.
Snyk für JavaScript-Sicherheit
Von Ihrer ersten Codezeile bis zu Ihrer letzten npm-Abhängigkeit schützt Snyk Ihre JavaScript-Anwendungen direkt in Ihrer IDE, CLI und Ihren Git-Workflows.


