Skip to main content

Python-URLs sicher validieren

Artikel von

Afzaal Ahmad Zeeshan

feature python linting

4. November 2022

0 Min. Lesezeit

Alles im Internet hat einen Uniform Resource Locator (URL), der es eindeutig identifiziert und Internetnutzern den Zugriff auf Dateien und andere Medien ermöglicht. Dieser Artikel hat beispielsweise eine eindeutige URL, die Suchmaschinen-Crawlern hilft, ihn für Nutzer auffindbar zu machen.

Die erste Definition der URL-Syntax findet sich im Request for Comments (RFC) 1738 von 1994. Seitdem wurde die Struktur von URLs vielfach überarbeitet, um ihre Sicherheit zu verbessern. Entwickler halten sich jedoch oft nicht wie vorgesehen an die RFC-Definition und tragen so zu zahlreichen böswilligen Angriffen bei.

Ein aktuelles Beispiel ist der RCE-0-Day-Exploit in Log4j, einem beliebten Java-Logging-Paket. Der Angriff erfolgte, als die Java Naming and Directory Interface (JNDI) einen schädlichen Log-String auswertete. JNDI ist eine Java-API für einen Verzeichnisdienst, mit dem Java-Softwareclients Daten und Ressourcen (in Form von Java-Objekten) mithilfe eines Namens ermitteln und abrufen können. Bei der Auswertung eines schädlichen Log-Strings stellt JNDI eine Verbindung zu einem Remote-Server her und führt bösartigen Java-Code aus. Daher müssen Unternehmen URLs, die von externen Akteuren wie Kunden und Partnern bereitgestellt werden, kontinuierlich validieren.

Ein weiteres Beispiel ist ein Server-Side-Request-Forgery-Angriff, der ein Serverprogramm kompromittieren kann, wenn dieses auf eine unsichere URL zugreift. Böswillige Nutzer können die bereitgestellten Eingabefelder ausnutzen, um unseren Weblösungen – und schlimmer noch, dem öffentlichen Ansehen unseres Unternehmens – zu schaden.

In diesem Artikel erfahren Sie mehr über die Herausforderungen durch manipulierte URLs, wie sie Ihren Anwendungen schaden können und wie Sie das Problem angehen. Stellen Sie sicher, dass Python auf Ihrem Rechner installiert und eingerichtet ist, damit Sie den Schritten folgen können.

Sicherheitsrisiken durch URLs

URLs können riskant sein, da sie Nutzer von einer legitimen Webseite auf eine bösartige Seite leiten können. Sie können auch mehrere Angriffsvektoren eröffnen, darunter Cross-Site-Scripting (XSS), eine Sicherheitslücke in manchen Webanwendungen. XSS ermöglicht Angreifern, clientseitige Skripte in Webseiten einzuschleusen, die andere Nutzer aufrufen.

Dieses Sicherheitsrisiko kann in bestimmten Branchen wie dem Bankwesen schwerwiegende Folgen haben. Ein ahnungsloser Kunde könnte eine echt wirkende, von einem Angreifer kontrollierte Seite öffnen, weil er sie für die Anmeldeseite seiner Banking-Anwendung hält. Dabei handelt es sich um eine Phishing-Attacke, die auf Social Engineering basiert. Ein Angreifer sendet betrügerische, gefälschte oder anderweitig irreführende Nachrichten, um jemanden dazu zu bringen, ihm sensible Informationen preiszugeben. Außerdem könnte er auf der Infrastruktur des Opfers Schadsoftware wie Ransomware installieren. Erlangt der Angreifer den Benutzernamen und das Passwort eines Bankkunden, kann er sich damit beim Bankkonto des Kunden anmelden und Schaden anrichten.

Noch ausgefeiltere URL-Angriffe können durch Server-Side Request Forgery erfolgen. Dieser Angriff richtet sich gegen Server, die Anfragen an von Kunden bereitgestellte URLs senden. Bei einer solchen Anfrage kann ein Angreifer den Server übernehmen und unzulässige Aktionen ausführen, etwa Ports und Netzwerkinformationen scannen, Infrastruktur-Metadaten abrufen oder vertrauliche Informationen wie Passwörter und Tokens ausgeben.

In den folgenden Abschnitten erfahren Sie, wie Sie URLs validieren und bereinigen, die Sie nicht kontrollieren. Wenn wir beispielsweise eine soziale Plattform entwickeln, auf der Nutzer kommunizieren und Daten austauschen können, lässt sich festlegen, welche URLs zulässig sind und welche ausgeblendet werden.

So validieren Sie URLs in Python

Python ist eine Programmiersprache, die häufig für die Entwicklung von Webanwendungen und Webseiten für Millionen von Kunden weltweit eingesetzt wird. Python verfügt zwar nicht über einen integrierten URL-Scanner und -Validator, doch es gibt von der Community entwickelte URL-Parser und -Validatoren für Python, mit denen sich URLs validieren und sicherer machen lassen. Einige Webanwendungs-Frameworks bieten ebenfalls URL-Scanner und -Validatoren für die Entwicklung von Webanwendungen.

URLs validieren

Eine beliebte Methode zur URL-Validierung in Python ist das Python-Paket validators. Damit können wir prüfen, ob eine URL gültig ist. Dafür muss sie:

  • Korrekt formatiert sein, also allen Regeln der HTTP- oder HTTPS-Spezifikationen entsprechen

  • Auf eine Ressource verweisen, da eine URL ohne zugehörige Ressource ungültig ist

Das Python-Paket validators stellt eine URL-Methode bereit, die die URL überprüft, ihre Sicherheit testet und nach ungültigen Schlüsselwörtern und Zeichen sucht. Ist eine URL öffentlich zugänglich (also nicht durch eine Firewall, Bezahlschranke oder ein anderes Zugriffshindernis geschützt), werden interne IP-Adressen ausgeschlossen.

Um das Paket validators zu verwenden, laden Sie die Abhängigkeit herunter und richten Sie sie mit pip in Ihrer lokalen Python-Umgebung ein. Führen Sie zum Herunterladen des Pakets validators den folgenden Code in Ihrem lokalen Terminal oder Ihrer Kommandozeile aus:

$ python3 -m pip install validators

Nach Abschluss dieses Befehls ist das Paket validators auf unserem Rechner verfügbar.

Erstellen Sie als Nächstes eine Python-Datei namens main.py und schreiben Sie Python-Code, um eine URL zu testen:

import validators

validation = validators.url("http:/www.google.com")
if validation:
print("URL is valid")
else:
print("URL is invalid")

Nachdem Sie diesen Code in die Datei main.py eingefügt haben, führen Sie ihn mit der Python-Kommandozeile im Python-Interpreter aus:

$ python main.py

Der Code gibt "URL is invalid" aus, weil in der URL nach http:/ ein /-Zeichen fehlt.

Das Paket kann außerdem feststellen, ob eine URL öffentlich zugänglich ist. Das ist hilfreich, wenn Sie prüfen möchten, ob ein Nutzer eine interne IP-Adresse anfordert. Fügen Sie den folgenden Code in dieselbe Python-Datei ein und führen Sie ihn aus, um eine URL zu validieren.

validation = validators.url("https://10.0.0.1", public=True)
if validation:
print("URL is valid")
else:
print("URL is invalid")

Auch diesmal lautet die Ausgabe, dass die URL ungültig ist. Das liegt daran, dass sie nicht öffentlich zugänglich ist – obwohl die URL selbst keine Fehler aufweist. Weitere Informationen zu den Funktionen des Pakets validators finden Sie in der Dokumentation.

Parsen mit regulären Ausdrücken

Eine weitere Möglichkeit zur URL-Validierung sind reguläre Ausdrücke. So können wir beispielsweise festlegen, dass eine URL HTTPS enthalten muss, bevor sie validiert werden kann. Der Code für diese Prüfung sieht so aus:

^https:\/\/[0-9A-z.]+.[0-9A-z.]+.[a-z]+$

Dieser reguläre Ausdruck erkennt den Begriff https://www.google.com, nicht aber http://www.google.com, obwohl beide gültige URLs sind. Weitere Informationen zu regulären Ausdrücken finden Sie auf dieser Webseite. Wir können den obigen Ausdruck mit folgendem Python-Code testen:

import re

pattern = "^https:\/\/[0-9A-z.]+.[0-9A-z.]+.[a-z]+$"
result = re.match(pattern, "https://www.google.com")

if result: 
print(result)
else:
print("Invalid URL")

Die Ausgabe des obigen Codes ist die gefundene URL. Ändern Sie die URL-Zeichenfolge oben und entfernen Sie HTTPS oder ändern Sie es zu HTTP, erhalten Sie ein None-Objekt – es wurde also keine passende URL gefunden.

Reguläre Ausdrücke sind jedoch kompliziert und für reale Szenarien nicht praktikabel. Sie sind schwer lesbar und lassen sich nur komplex debuggen und skalieren. Deshalb sind Bibliotheken in der Regel die bessere Lösung.

Ein fortgeschritteneres Beispiel für einen regulären Ausdruck, der eine URL anhand aller konformen Strukturen und Syntaxregeln parst, finden Sie in diesem Stack-Overflow-Thread.

Ein Vorteil regulärer Ausdrücke ist, dass Sie damit auch ungültige URLs in Eingabezeichenfolgen finden können. Das ist nur mit regulären Ausdrücken möglich, nicht mit gängigen Bibliotheken. Das Paket validators funktioniert nicht, wenn die Zeichenfolge vor oder nach der URL Leerzeichen enthält. Damit das Paket richtig funktioniert, müssen Sie die Eingabezeichenfolge bereinigen und an den Validator übergeben.

urllib verwenden

Ein weiteres Paket, das URLs parst und ihre Bestandteile zugänglich macht, ist urllib. Wir können es mit dem Python-3-Interpreter verwenden.

Mit folgendem Code lässt sich prüfen, ob eine URL gültig ist:

from urllib.parse import urlparse
result = urlparse("https:/www.google.com")
if result.scheme and result.netloc:
print("Success")
else:
print("Failed")

print(result)

Wenn wir der Variable result ein Schema und das Feld netloc zuweisen, ist die URL gültig und kann verwendet werden. Andernfalls ist sie ungültig und wir sollten vorsichtig sein.

Häufige Sicherheitslücken erkennen

Einige Python-Frameworks wie Django bieten integrierte Validator-Pakete, mit denen sich URLs innerhalb des jeweiligen Frameworks validieren lassen. Wer sich auf diese Bibliotheken verlässt, muss jedoch sicherstellen, dass auch das Paket selbst sicher ist – selbst wenn das Framework vertraut ist. Open Source macht es zudem schwieriger, dem Paket zu vertrauen.

Mit einem Sicherheitstool wie Snyk Advisor können wir alle verwendeten Open-Source-Pakete und neue Pakete, die wir einsetzen möchten, schnell auf häufige Sicherheitslücken prüfen. Auf Basis dieser Prüfung erstellt Snyk einen Sicherheitsbericht, mit dem wir entscheiden können, ob das Paket eingebunden werden sollte. So können wir beispielsweise sicherstellen, dass unsere Pakete wie das oben in der Demonstration verwendete validators-Paket sicher sind.

Zusätzlich zu Snyk Advisor können wir Snyk Open Source nutzen, um Lizenzprobleme, Sicherheitslücken und weitere Sicherheitsbedenken in unserem Open-Source-Tool-Stack aufzudecken. Außerdem können wir in der Snyk Vulnerability Database (VulnDB) nach bekannten URL-bezogenen Sicherheitslücken suchen, etwa nach dieser Sicherheitslücke im Flask-Framework, durch die Nutzer ohne URL-Validierung an einen anderen Ort weitergeleitet werden. Mithilfe dieser Datenbank können wir unsere Webseiten und Anwendungen proaktiv absichern.

URLs in Python validieren

In diesem Artikel haben wir uns mit den Herausforderungen befasst, die nicht bereinigte URLs für Webanwendungen darstellen, und damit, wie sich URLs bei Bedarf bereinigen lassen. Zunächst haben wir URLs mithilfe der Pakete validators und urllib grundlegend validiert. Außerdem haben wir gezeigt, wie sich mit diesen Paketen feststellen lässt, ob URLs öffentlich zugänglich oder interne URLs sind, die für Angriffe auf die Webanwendung genutzt werden könnten. Anschließend haben wir anhand eines einfachen regulären Ausdrucks veranschaulicht, wie eine einzige Codezeile URLs auf grundlegende Anforderungen prüfen kann, beispielsweise darauf, dass alle URLs HTTPS verwenden. Außerdem haben wir erläutert, warum reguläre Ausdrücke eine komplexe und schwierige Methode zur URL-Validierung sind.

Abschließend haben wir besprochen, wie Sie sichere Open-Source-Bibliotheken auswählen. Snyk Advisor ist eine wertvolle Informationsquelle für die Verwendung von Open-Source-Paketen. Weitere Informationen finden Sie im Spickzettel zu Best Practices für Python-Sicherheit. Er hilft Ihnen dabei, CI/CD-Pipelines (Continuous Integration und Continuous Development) so vorzubereiten, dass alle neu in Ihren Code eingebrachten Sicherheitslücken überprüft werden.

Starten Sie mit Capture-the-Flag

Erfahren Sie in unserem virtuellen On-Demand-Workshop für Einsteiger, wie Sie Capture-the-Flag-Challenges lösen.