Skip to main content

Sichere JavaScript-URL-Validierung

Artikel von

Mannan Tirmizi

feature argument injection

9. Mai 2023

0 Min. Lesezeit

Anmerkung der Redaktion: 9. Mai 2023

Dieser Beitrag, der ursprünglich am 18. Oktober 2022 veröffentlicht wurde, wurde aktualisiert und zeigt nun, wie Snyk Ihnen dabei helfen kann, eine sichere JavaScript-URL-Validierung einzurichten.

Wenn Entwickler URLs in unterschiedlichen Formen und für verschiedene Zwecke verarbeiten müssen – etwa für die Navigation im Browserverlauf, Sprungziele, Abfrageparameter und mehr –, greifen wir oft auf JavaScript zurück. Seine häufige Verwendung motiviert Angreifer jedoch dazu, seine Schwachstellen auszunutzen. Dieses Ausnutzungsrisiko macht es erforderlich, die URL-Validierung in unseren JavaScript-Anwendungen zu implementieren.

Bei der URL-Validierung wird geprüft, ob URLs der korrekten URL-Syntax entsprechen – also der Struktur, die jede URL aufweisen muss. URL-Validierung kann unsere Anwendungen vor URL-basierten Schwachstellen wie dem Einschleusen schädlicher Skripte und serverseitiger Anforderungsfälschung (SSRF) schützen. Angreifer können SSRF-Angriffe durchführen, wenn wir beim Abrufen einer Remote-Ressource keine sicheren Programmierkonventionen zur Validierung von benutzergesteuerten URLs anwenden. SSRF ist nach wie vor eine kritische Bedrohung für JavaScript-basierte Anwendungen, sowohl im Frontend als auch in serverseitigen Node.js-Anwendungen, und war 2021 eine hervorgehobene Kategorie in der Liste OWASP Top 10.

URL-Validierung

URL-Validierung dient dazu, die Sicherheit vor möglichen Exploits zu erhöhen und Fehler zu vermeiden, die bei der Ausführung von Code auftreten könnten. Doch wann sollten wir URLs validieren, und was prüfen wir dabei? Wir sollten die URL-Validierung in jeder Software implementieren, die Ressourcen wie Seiten, Bilder, GIFs und Videos identifizieren und überprüfen muss.

Eine typische URL setzt sich aus mehreren Bestandteilen zusammen, etwa einem Protokoll, Domainnamen, Hostnamen, Ressourcennamen, Ursprung, Port und weiteren Elementen. Diese teilen dem Browser mit, wie er die jeweilige Ressource abrufen soll. Wir können diese Bestandteile auf verschiedene Weise zur Validierung von URLs verwenden:

  • Verwendung von Regex-Literalen und -Konstruktoren

  • URL-Konstruktoren

  • isValidURL-Methode

  • Eingabeelemente

  • Anker-Tag-Methode

Bei einem typischen URL-Validierungsschema werden Eingaben eines Benutzers entgegengenommen und anschließend analysiert, um die verschiedenen Bestandteile zu ermitteln. Das Schema kann sicherstellen, dass alle URL-Komponenten den Internetstandards entsprechen. So lässt sich beispielsweise prüfen, ob eine URL bei Bedarf ein sicheres Protokoll verwendet.

Bei der Hostnamenvalidierung werden Hostnamen zunächst in einzelne Labels zerlegt, um sicherzustellen, dass sie der Spezifikation für Top-Level-Domainnamen entsprechen. Ein typischer Hostname besteht aus mindestens zwei durch Punkte getrennten Labels. www.snyk.com enthält beispielsweise die Labels „www“, „snyk“ und „com“. Jedes Label darf unabhängig von Groß- und Kleinschreibung nur alphanumerische Zeichen oder einen Bindestrich enthalten. Anschließend kann das Validierungsschema prüfen, ob der Hostname mit einer Allowlist zulässiger URLs übereinstimmt. So wird sichergestellt, dass nur vorgegebene URLs zugelassen und zulässige URLs nicht fälschlich ausgeschlossen werden.

Die meisten Pfade zu Ressourcen, die in URLs verwendet werden, sind standardmäßig zulässig. Ports dürfen jedoch nur im Bereich von 1 bis 65536 liegen. Werte außerhalb dieses Bereichs sollten einen Fehler auslösen. Außerdem können wir numerische IP-Adressen darauf prüfen, ob es sich um eine IPv4- oder IPv6-Adresse handelt.

Schließlich können wir URLs auch auf Benutzernamen und Passwörter prüfen, auch wenn das nicht unbedingt offensichtlich ist. Diese Funktion unterstützt die Einhaltung von Unternehmensrichtlinien und den Schutz von Zugangsdaten.

Nachdem Sie nun die Grundlagen kennen, sehen wir uns die URL-Validierung mit JavaScript an!

So führen Sie eine URL-Validierung in JavaScript durch

Am einfachsten lässt sich eine URL in JavaScript mit der Konstruktorfunktion new URL validieren. Sie ist nicht nur einfach zu verwenden, sondern wird auch von der Node.js-Laufzeitumgebung und den meisten Browsern unterstützt.

Die grundlegende Syntax lautet:

new URL (url)
new URL (url , base)

JavaScript benötigt das Element base nur dann, wenn wir eine relative URL angeben. Lassen wir es weg, lautet der Standardwert undefined. Geben wir alternativ ein base-Element mit einer absoluten URL an, ignoriert JavaScript das Element base.

Zur Validierung der URL können Sie folgende Funktion verwenden:

function checkUrl (string) {
    let givenURL ;
    try {
        givenURL = new URL (string);
    } catch (error) {
        console.log ("error is", error);
       return false; 
    }
    return true;
  }

Diese Funktion prüft, ob eine URL gültig ist. Sie gibt „true“ zurück, wenn die URL gültig ist, und „false“, wenn nicht. Übergeben Sie www.urlcheck.com an diese Funktion, gibt sie „false“ zurück, da die URL kein gültiges URL-Schema enthält. Die korrekte Version dieser URL lautet https://urlcheck.com. Ein weiteres Beispiel ist mailto:John.Doe@example.com. Das ist eine gültige URL, aber wenn Sie den Doppelpunkt entfernen, erkennt JavaScript sie nicht mehr als URL. Ein drittes Beispiel ist ftp://. Diese URL ist ungültig, da sie keinen Hostnamen enthält. Fügen Sie zwei Punkte hinzu (..), wird sie gültig, da die Punkte als Hostname betrachtet werden. Somit wird ftp://.. zu einer gültigen URL.

Denken Sie daran, dass es ungewöhnliche, aber vollkommen gültige URLs gibt! Für Entwickler, die mit ihnen arbeiten, mögen sie unerwartet sein, ansonsten sind sie jedoch völlig in Ordnung. Die folgenden beiden URLs geben beispielsweise TRUE zurück:

  • new URL("youtube://a.b.c.d");

  • new URL ("a://1.2.3.4@1.2.3.4");

Diese Beispiele zeigen, dass Entwickler sich bei der URL-Validierung an den entsprechenden Grundsätzen statt an Konventionen orientieren sollten.

Wenn Sie sicherstellen möchten, dass eine gültige URL ein bestimmtes URL-Schema enthält, können Sie folgende Funktion verwenden:

  function checkHttpUrl(string) {
    let givenURL;
    try {
        givenURL = new URL(string);
    } catch (error) {
        console.log("error is",error)
      return false;  
    }
    return givenURL.protocol === "http:" || givenURL.protocol === "https:";
  }

Diese Funktion validiert die URL und prüft anschließend, ob sie das HTTP- oder HTTPS-Schema verwendet. ftp://.. ist hier ungültig, da die URL weder HTTP noch HTTPS verwendet. http://.. bleibt hingegen gültig. Die Konstruktorfunktion URL lässt sich außerdem wie folgt verwenden:

  let m = 'https://snyk.io';
  let a = new URL("/", m);

Im obigen Beispiel wird das Element base verwendet. Wenn wir den Wert ausgeben, erhalten wir https://snyk.io/.

Um ein URL-Objekt ohne Angabe des Parameters base zurückzugeben, lautet die Syntax:

  let b = new URL(m);

Einen Pfadnamen zum Host fügen wir folgendermaßen hinzu:

  let d = new URL('/en-US/docs', b);

Die in d gespeicherte URL lautet https://snyk.io/en-US/docs.

Eine weitere Funktionalität des URL-Moduls ist die Implementierung der WHATWG-URL-API, die dem von Browsern verwendeten WHATWG-URL-Standard entspricht:

  let adr = new URL("https://snyk.io/en-US/docs");
  let host = adr.host;
  let path = adr.pathname;

Im obigen Beispiel haben wir ein URL-Objekt namens adr erstellt. Anschließend hat der Code den Host und den Pfadnamen der URL abgerufen: snyk.io beziehungsweise /en-US/docs. Schließlich können wir die URL mit einer Allowlist oder Blocklist vergleichen, um sicherzustellen, dass nur vorgegebene URLs zugelassen und zulässige URLs nicht fälschlich ausgeschlossen werden.

So validieren Sie eine URL mit Regex – obwohl Sie das nicht tun sollten

Eine weitere Möglichkeit, eine URL zu validieren, ist ein regulärer Ausdruck (Regex) – also eine Zeichenfolge, die ein Suchmuster bildet. Mit Regex können wir prüfen, ob eine URL gültig ist.

Die JavaScript-Syntax für die URL-Validierung mit Regex lautet:

  function isValidURL(string) 
        {
            var res = 
            string.match(/(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-
            ]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]
            \.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|w
            ww\.[a-zA-Z0-9]+\.[^\s]{2,})/gi);
        return (res !== null);
        };

So testen Sie einige URLs:

  var tc1 = "http://helloworld.com"
  console.log(isValidURL(tc1));

Die mit Regex definierte URL-Syntax prüft, ob die URL mit dem Schema http:// oder https:// oder einer Subdomain beginnt und einen Domainnamen enthält. Die Anweisung in der Konsole lautet true, da sie der durch Regex definierten URL-Syntax entspricht. Die folgende Anweisung gibt dagegen den Wert false zurück, da sie weder mit einem der zulässigen Schemas noch mit einer Subdomain beginnt und auch keinen Domainnamen enthält:

  var tc4 = "helloWorld";
  console.log (isValidURL(tc4));

Die obige Regex ist relativ einfach, aber dennoch schwer zu überblicken. Außerdem ist dieser Ansatz fehleranfällig, da sich die Regeln zur URL-Validierung mit Regex nicht angemessen abbilden lassen. Regex kann höchstens gültige URLs abgleichen. Darüber hinaus wird die Validierungsprüfung zeitaufwendig, wenn ein regulärer Ausdruck komplexe Validierungslogik enthält oder eine lange Eingabezeichenfolge verarbeitet.

Um die definierten Regex-Validierungsprüfungen zu erfüllen, muss der Browser die Eingabezeichenfolge millionenfach rückwärts durchlaufen. Dieses häufige Zurückgehen kann zu „katastrophalem Backtracking“ führen – einem Phänomen, bei dem komplexe reguläre Ausdrücke den Browser einfrieren oder die CPU-Kerne vollständig auslasten können.

Snyk erkennt anfällige Open-Source-Pakete

Auch Maintainer können bei der URL-Validierung Fehler machen, wodurch Node.js-Anwendungen gefährdet werden. Das npm-Paket keycloak-connect ist ein solches Projekt. Es verzeichnet wöchentlich mehr als 50.000 Downloads. Im März 2023 wurde jedoch bekannt, dass eine unsichere Vorgehensweise bei der URL-Validierung eine Open-Redirect-Schwachstelle über CVE-2023-2237 ermöglichte.

Wir empfehlen Ihnen dringend, Ihre Projekte kostenlos mit Snyk zu scannen, um anfällige Open-Source-Abhängigkeiten zu finden und zu beheben.

Snyk-Schwachstellenseite mit einem offenen Redirect in keycloak-connect-Versionen unter 21.0.1, eingestuft als mittelschwer mit einem Schweregrad von 6,8.

Die 10 häufigsten JavaScript-Schwachstellen von Snyk

Dieser Spickzettel bietet einen detaillierten Überblick über die am weitesten verbreiteten kritisch und hoch eingestuften Open-Source-Schwachstellen, die Snyk-Scans von JavaScript-Anwendungen im Jahr 2022 aufgedeckt haben.

Schwachstellen und Gegenmaßnahmen aus der Praxis

Node.js ist eine kostenlose, quelloffene und plattformübergreifende JavaScript-Laufzeitumgebung, die einen Paketmanager namens Node Package Manager (npm) verwendet.

Ein ähnlicher Vorfall ereignete sich 2019, als ein Angreifer allein unbefugten Zugriff auf Daten von Capital One erhielt, einer der größten Banken der Vereinigten Staaten. Dieser Datendiebstahl zählt nach wie vor zu den bedeutendsten des Jahrhunderts. Laut The New York Times gelangte der Angreifer an 100 Millionen Kundendatensätze, 140.000 Sozialversicherungsnummern und 80.000 verknüpfte Bankdaten von Capital-One-Kunden.

Der Angreifer griff auf den von Amazon Web Services (AWS) gehosteten Capital-One-Server zu. Die verzögerte Erkennung deutet darauf hin, dass der Angreifer über fundierte Kenntnisse der AWS-Infrastruktur verfügte und eine ausnutzbare Schwachstelle in der Web Application Firewall (WAF) des Managed Security Service Providers (MODSEC) erkannte. Mit diesem Wissen führte der Täter den SSRF-Angriff durch und löste durch Manipulation des anfälligen Webservers neue HTTP-Anfragen aus. So erhielt er erfolgreich Zugriff auf den AWS-Metadatendienst.

Je nach Unternehmensanforderungen können wir SSRF-Angriffe vermeiden, indem wir das System auf wenige Protokolle wie HTTP oder HTTPS beschränken. Für zusätzliche Sicherheit müssen wir die Anwendung so einrichten, dass sie den URL-Parameter nicht ungeprüft weitergibt. Zur Filterung und Kontrolle des Mechanismus werden üblicherweise Allow- und Denylists verwendet, wodurch das SSRF-Risiko erheblich sinkt. Allowlists ermöglichen der Anwendung die Nutzung einer vordefinierten Auswahl an Objekten und Servern. Denylists wiederum beschränken den Abruf allgemein verfügbarer Hostnamen durch die Anwendung.

JavaScript sicher verwenden

Wie die Aufnahme von SSRF in die neue OWASP Top 10 zeigt, ist die URL-Validierung für die Sicherheit von JavaScript-Anwendungen immer wichtiger geworden. Glücklicherweise können wir solche Angriffe eindämmen, indem wir URLs serverseitig validieren. Außerdem kann es sehr hilfreich sein, die neue URL-Funktion zu verwenden und URLs auf die empfohlenen Arten zu validieren und zu verarbeiten.

Nachdem wir uns einige Anwendungsfälle für die neue URL-Funktion angesehen hatten, lernten wir, wie sich eine URL mit Regex validieren lässt – und warum dieser Ansatz umständlich und fehleranfällig ist. Abschließend betrachteten wir eine Fallstudie zu einer SSRF-Schwachstelle in JavaScript.

Bei URLs geht es bei den Sicherheitsrisiken weniger um ihre Gültigkeit als vielmehr um gefährliche URL-Schemas. Daher müssen wir sicherstellen, dass die serverseitige Anwendung die Validierung durchführt. Angreifer können clientseitige Validierungsmechanismen umgehen. Sich allein darauf zu verlassen, ist daher keine geeignete Lösung.

Weitere Informationen zur Verwaltung Ihrer Anwendungssicherheit und zum Snyk-Produkt finden Sie auf der Website von Snyk.

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.