Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python Enhancement Proposals

PEP 476 – Aktivierung der Zertifikatsprüfung standardmäßig für stdlib HTTP-Clients

Autor:
Alex Gaynor <alex.gaynor at gmail.com>
Status:
Final
Typ:
Standards Track
Erstellt:
28-Aug-2014
Python-Version:
2.7.9, 3.4.3, 3.5
Resolution:
Python-Dev Nachricht

Inhaltsverzeichnis

Zusammenfassung

Wenn ein Standardbibliotheks-HTTP-Client (die Module urllib, urllib2, http und httplib) auf eine https://-URL trifft, wird der Netzwerkverkehr im TLS-Stream eingekapselt, wie es für die Kommunikation mit einem solchen Server erforderlich ist. Während des TLS-Handshakes wird jedoch nicht tatsächlich geprüft, ob das X509-Zertifikat des Servers von einer CA in einem Vertrauensstamm signiert wurde, noch wird überprüft, ob der Common Name (oder Subject Alternate Name) im vorgelegten Zertifikat mit dem angeforderten Host übereinstimmt.

Das Versäumnis, diese Prüfungen durchzuführen, bedeutet, dass jeder mit einer privilegierten Netzwerkposition trivial einen Man-in-the-Middle-Angriff gegen eine Python-Anwendung durchführen kann, die einen dieser HTTP-Clients verwendet, und den Datenverkehr nach Belieben ändern kann.

Dieses PEP schlägt vor, die Überprüfung von X509-Zertifikatssignaturen sowie die Hostnamenüberprüfung für die HTTP-Clients von Python standardmäßig zu aktivieren, vorbehaltlich eines Opt-outs auf Abrufbasis. Diese Änderung würde auf Python 2.7, Python 3.4 und Python 3.5 angewendet werden.

Begründung

Das "S" in "HTTPS" steht für sicher. Wenn Python-Benutzer "HTTPS" eingeben, erwarten sie eine sichere Verbindung, und Python sollte einen angemessenen Sorgfaltsstandard bei der Bereitstellung dieser einhalten. Derzeit scheitern wir daran und machen damit APIs, die einfach erscheinen, irreführend für Benutzer.

Auf Nachfrage geben viele Python-Benutzer an, dass sie nicht wussten, dass Python diese Validierungen nicht durchführt, und sind schockiert.

Die Popularität von requests (das diese Prüfungen standardmäßig aktiviert) zeigt, dass diese Prüfungen keinerlei übermäßigen Aufwand darstellen und die Tatsache, dass es weithin als wesentliche Sicherheitsverbesserung gegenüber den Standardbibliotheksclients empfohlen wird, zeigt, dass viele eine höhere Erwartung an "Sicherheit standardmäßig" von ihren Werkzeugen haben.

Das Versäumnis verschiedener Anwendungen, die Nachlässigkeit von Python in dieser Angelegenheit zu bemerken, ist die Quelle *regelmäßiger* CVE-Zuweisungen [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11].

Technische Details

Python würde die systembereitgestellte Zertifikatsdatenbank auf allen Plattformen verwenden. Das Fehlen einer solchen Datenbank wäre ein Fehler, und Benutzer müssten explizit einen Speicherort angeben, um dies zu beheben.

Dies wird durch Hinzufügen einer neuen Funktion ssl._create_default_https_context erreicht, die identisch mit ssl.create_default_context ist.

http.client kann dann seine Verwendung von ssl._create_stdlib_context durch ssl._create_default_https_context ersetzen.

Zusätzlich wird ssl._create_stdlib_context in ssl._create_unverified_context umbenannt (ein Alias bleibt aus Gründen der Abwärtskompatibilität erhalten).

Vertrauensdatenbank

Dieses PEP schlägt die Verwendung der systemseitig bereitgestellten Zertifikatsdatenbank vor. Frühere Diskussionen hatten vorgeschlagen, Mozillas Zertifikatsdatenbank zu bündeln und diese standardmäßig zu verwenden. Dies wurde aus mehreren Gründen abgelehnt

  • Die Verwendung der Plattform-Vertrauensdatenbank bedeutet einen geringeren Wartungsaufwand für die Python-Entwickler – das Versenden unserer eigenen Vertrauensdatenbank würde bei jeder Zertifikatssperrung eine Freigabe erfordern.
  • Linux-Anbieter und andere Downstreams würden die Mozilla-Zertifikate entbündeln, was zu einer fragmentierteren Verhaltensweise führen würde.
  • Die Verwendung der Plattformspeicher erleichtert die Handhabung von Situationen wie internen Unternehmens-CAs.

OpenSSL verfügt außerdem über ein Paar Umgebungsvariablen, SSL_CERT_DIR und SSL_CERT_FILE, die verwendet werden können, um Python auf eine andere Zertifikatsdatenbank hinzuweisen.

Abwärtskompatibilität

Diese Änderung wird den Anschein erwecken, dass einige HTTPS-Verbindungen "brechen", da sie während des Handshakes nun eine Ausnahme auslösen.

Dies ist jedoch irreführend, tatsächlich scheitern diese Verbindungen derzeit lautlos, eine HTTPS-URL deutet auf die Erwartung von Vertraulichkeit und Authentifizierung hin. Die Tatsache, dass Python nicht tatsächlich prüft, ob die Anfrage des Benutzers gestellt wurde, ist ein Fehler, darüber hinaus: "Fehler sollten niemals stillschweigend vergehen."

Nichtsdestotrotz können Benutzer, die auf Server mit selbstsignierten oder fehlerhaften Zertifikaten zugreifen müssen, dies tun, indem sie einen Kontext mit benutzerdefinierten Vertrauenswurzeln bereitstellen oder die Validierung deaktivieren (die Dokumentation sollte letzteres, wo immer möglich, dringend empfehlen). Benutzer können auch notwendige Zertifikate zu den Systemvertrauensspeichern hinzufügen, um sie global zu vertrauen.

Twisteds 14.0 Release hat die gleiche Änderung vorgenommen und sie wurde mit fast keinem Widerspruch aufgenommen.

Opt-out

Für Benutzer, die die Zertifikatsprüfung für eine einzelne Verbindung deaktivieren möchten, können sie dies erreichen, indem sie das Argument context zu urllib.urlopen bereitstellen

import ssl

# This restores the same behavior as before.
context = ssl._create_unverified_context()
urllib.urlopen("https://no-valid-cert", context=context)

Es ist auch möglich, obwohl dringend abgeraten, die Überprüfung global zu deaktivieren, indem das ssl-Modul in den Python-Versionen, die dieses PEP implementieren, monkeypatched wird

import ssl

try:
    _create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
    # Legacy Python that doesn't verify HTTPS certificates by default
    pass
else:
    # Handle target environment that doesn't support HTTPS verification
    ssl._create_default_https_context = _create_unverified_https_context

Diese Anleitung richtet sich in erster Linie an Systemadministratoren, die neuere Python-Versionen, die dieses PEP implementieren, in älteren Umgebungen einsetzen möchten, die die Zertifikatsprüfung für HTTPS-Verbindungen noch nicht unterstützen. Ein Administrator kann beispielsweise durch Hinzufügen des obigen Monkeypatchs zu sitecustomize.py in seiner Standardarbeitsumgebung für Python opten. Anwendungen und Bibliotheken SOLLTEN diese Änderung nicht prozessweit vornehmen (außer vielleicht als Reaktion auf eine vom Systemadministrator gesteuerte Konfigurationseinstellung).

Besonders sicherheitsrelevante Anwendungen sollten immer einen explizit anwendungsdefinierten SSL-Kontext bereitstellen, anstatt sich auf das Standardverhalten der zugrunde liegenden Python-Implementierung zu verlassen.

Andere Protokolle

Dieses PEP schlägt nur vor, diese Validierungsstufe für HTTP-Clients zu verlangen, nicht für andere Protokolle wie SMTP.

Dies liegt daran, dass, obwohl ein hoher Prozentsatz der HTTPS-Server korrekte Zertifikate aufweist, infolge der von Browsern durchgeführten Validierung, für andere Protokolle selbstsignierte oder anderweitig fehlerhafte Zertifikate weitaus häufiger vorkommen. Beachten Sie, dass sich dies zumindest für SMTP zu ändern scheint und in Zukunft für ein ähnliches PEP überprüft werden sollte

Python-Versionen

Dieses PEP beschreibt Änderungen, die in den Zweigen 3.4.x, 3.5 und 2.7.X auftreten werden. Für 2.7.X erfordert dies das Backporting des context (SSLContext)-Arguments nach httplib, zusätzlich zu den bereits in PEP 466 zurückportierten Funktionen.

Implementierung

  • LANDED: Issue 22366 fügt das context-Argument zu urlib.request.urlopen hinzu.
  • Issue 22417 implementiert den Kern dieses PEPs.

Quelle: https://github.com/python/peps/blob/main/peps/pep-0476.rst

Zuletzt geändert: 2025-02-01 08:59:27 GMT