Ignorieren Sie die Prüfung des SSL-Sicherheitszertifikats in Python-Anforderungen

Jay Shaw 10 Oktober 2023
  1. Den Grund hinter SSL-Sicherheitsprüfungen verstehen und warum sie fehlschlagen
  2. Ignorieren Sie die SSL-Sicherheitsprüfung in Python
  3. Abschluss
Ignorieren Sie die Prüfung des SSL-Sicherheitszertifikats in Python-Anforderungen

Der Zugriff auf eine URL ohne ein sicheres SSL-Zertifikat löst Ausnahmewarnungen aus, wenn HTTP-Anforderungen an sie gesendet werden. Oft läuft das SSL-Zertifikat dieser URLs ab, wodurch alle möglichen Sicherheitsprobleme entstehen.

Wenn die Informationen nicht sensibel sind, können diese Warnungen unterbunden werden, wenn Programme requests in Python verwenden. In diesem Artikel werden mehrere Möglichkeiten zum Deaktivieren von Sicherheitszertifikatprüfungen mithilfe von Anforderungen vorgestellt.

Den Grund hinter SSL-Sicherheitsprüfungen verstehen und warum sie fehlschlagen

Wenn ein Programm Python-Anfragen verwendet, um Anfragen von einer URL zu erhalten, deren SSL-Zertifikat abgelaufen ist, löst es zwei Ausnahmen aus. Das folgende Programm zeigt, was diese Ausnahmen sind.

Szenario 1

Dieses Programm verwendet zu Testzwecken eine von der SSL-Community bereitgestellte URL mit einem abgelaufenen Sicherheitszertifikat. Es ist zu beachten, dass die SSL-Sicherheitsausnahmen nur bei URLs mit abgelaufenen SSL-Zertifikaten auftreten.

Die Python-requests lösen keine Ausnahme bei URLs mit gültigem oder widerrufenem SSL-Zertifikat aus. Daher konzentriert sich dieser Artikel hauptsächlich auf URLs mit abgelaufenen Sicherheitszertifikaten.

Das folgende Beispiel zeigt ein einfaches Programm, das in der ersten Zeile Anfragen importiert. Die zweite Zeile des Programms sendet eine post-Anforderung an die URL, um Vorkommen von 'bar' in 'baz' zu ändern.

Es wird getan, um eine post-Anfrage an die URL zu senden, und hat innerhalb des Programms keine andere Bedeutung.

import requests

requests.post(url="https://expired-rsa-dv.ssl.com/", data={"bar": "baz"})

Die Ausführung dieses Python-Skripts löst SSLError-Ausnahmen aus.

....
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='expired-rsa-dv.ssl.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:841)'),))

Dies ist die erste Ausnahme, die berücksichtigt werden muss, um zu lernen, wie man Sicherheitszertifikatsprüfungen mit requests deaktiviert.

Szenario 2

Dieses Programm schaltet die Prüfung des SSL-Zertifikats mit verify=False ab, um die Prüfung des Sicherheitszertifikats mit requests zu deaktivieren.

import requests

requests.post(url="https://expired-rsa-dv.ssl.com/", data={"bar": "baz"}, verify=False)

Die requests-Bibliothek ist so aufgebaut, dass sie die Überprüfung für SSL-Zertifikate deaktivieren kann, aber das Programm wirft eine weitere Ausnahme mit Links mit abgelaufenen SSL-Zertifikaten.

InsecureRequestWarning: Unverified HTTPS request is being made to host 'expired-rsa-dv.ssl.com'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html#ssl-warnings
  InsecureRequestWarning,

Diese beiden Ausnahmen müssen behandelt werden, um die Überprüfung von Sicherheitszertifikaten mit Anforderungen zu deaktivieren.

Ignorieren Sie die SSL-Sicherheitsprüfung in Python

In diesem Abschnitt werden verschiedene Methoden erläutert, die entweder die Überprüfung von Sicherheitszertifikaten mithilfe von Anforderungen deaktivieren oder das Problem umkehren. Jede Methode hat ihren Zweck.

Erstellen Sie einen Monkey Patch für die Bibliothek requests

Wenn eine Bibliothek eines Drittanbieters die Deaktivierung der Sicherheitsüberprüfungen erfordert, kann die Bibliothek Anforderungen monkey patched werden. Beim Patchen wird ein Kontextmanager verwendet, um Sicherheitszertifikatsprüfungen mittels requests zu deaktivieren.

Nach dem Patchen der requests erhält das verify-Feld standardmäßig einen False-Wert, wodurch die Warnung unterdrückt wird. Eine weitere Warnung wird ausgegeben, wenn verify=false verwendet wird, wie in Szenario 2 des vorherigen Abschnitts erläutert.

Der Patch fügt dann einen Ausnahmebehandlungsblock hinzu, um die Prüfung von Sicherheitszertifikaten mit Anforderungen zu deaktivieren, und unterdrückt die Warnungen. Mit den folgenden Beispielen wird es einfacher zu verstehen.

Das folgende Programm patcht die Bibliothek requests. Lassen Sie uns verstehen, was dieser Code tut.

Importe:

  1. warnings: Dieses Bibliothekspaket ist ein Unterpaket der Exceptions-Bibliothek.
  2. contextlib: Diese Python-Bibliothek wird zum Patchen der Bibliothek requests verwendet.
  3. requests: Das Requests-Bibliothekspaket von Python.
  4. urllib3: Es ist ein Modul, das HTTP-Anfragen und URLs in Python verarbeitet. Diese Bibliothek wird verwendet, um ein Untermodul InsecureRequestWarning zu importieren, das eine Ausnahme für abgelaufene SSL-Zertifikate auslöst.

Aufnäher:

Zunächst speichert das Programm die Standardumgebungseinstellungen der Bibliothek requests in einer Variablen - old_merge_environment_settings. Diese Variable wird verwendet, um Anforderungen wieder in ihren Standardzustand zu bringen, nachdem die geöffneten Adapter geschlossen wurden.

old_merge_environment_settings = requests.Session.merge_environment_settings

Die Methode no_ssl_verification wird erstellt und mit @contextlib.contextmanager dekoriert. Eine neue Variable opened_adapters wird erstellt und ihr ein set() zugewiesen.

Ein Set ist ein Datentyp, der Elemente in einem ungeordneten Format speichert.

@contextlib.contextmanager
def no_ssl_verification():
    opened_adapters = set()

Innerhalb der Methode no_ssl_verification wird eine weitere verschachtelte Methode merge_environment_settings erstellt. Diese Methode hat sechs Parameter, ähnlich den merge_environment_settings aus dem requests-Modul, und fungiert als Patch für das ursprüngliche Modul.

def merge_environment_settings(self, url, proxies, stream, verify, cert):

Innerhalb der Methode wird die Variable opened_adapters mit dem passenden Adapterpaar aus dem Parameter url aktualisiert. Jede Verbindung wird mit einem passenden Adapterpaar hergestellt, das in diesem Schritt zurückgegeben wird.

Da die Überprüfung nur einmal pro Verbindung erfolgt, müssen wir alle geöffneten Adapter schließen, nachdem wir fertig sind. Wenn nicht, bleiben die Wirkungen von verify=False bestehen, nachdem dieser Kontextmanager beendet wurde.

def merge_environment_settings(self, url, proxies, stream, verify, cert):

    opened_adapters.add(self.get_adapter(url))

Es ist wichtig, sich an den ersten Abschnitt des Artikels zu erinnern, um die nächste Codezeile zu verstehen. Wenn die Funktion requests.post auf der URL mit einem abgelaufenen SSL-Zertifikat verwendet wurde, wurden zwei Ausnahmen ausgelöst.

Die erste Ausnahme wurde durch verify verursacht, das mit einem True-Wert gesetzt ist. Das verify-Feld war zwar schaltbar, konnte aber mit einem False-Wert belegt werden.

Die zweite Ausnahme war eine nicht änderbare Entität, die das Programm daran hinderte, eine Verbindung herzustellen.

Der folgende Code ändert das Feld verify so, dass es standardmäßig einen False-Wert hat, um dieses Problem zu lösen. Zur Ausführung dieses Schrittes wird eine neue Variable settings erstellt, die mit Daten aus der Variablen old_merge_environment_settings belegt wird.

Sobald die Daten in der Variablen settings gespeichert sind, wird das Feld verify auf False gesetzt.

Dadurch ändert sich der Standardwert von verify. Zuletzt wird diese Variable zurückgegeben.

settings = old_merge_environment_settings(self, url, proxies, stream, verify, cert)
settings["verify"] = False

return settings

Die Daten der aktualisierten Methode merge_environment_settings werden der Funktion requests.Session.merge_environment_settings zugewiesen. Dadurch wird sichergestellt, dass das Feld verify standardmäßig einen False-Wert hat.

requests.Session.merge_environment_settings = merge_environment_settings

Die erste Ausnahme haben wir behandelt. Die zweite Ausnahme, die nicht änderbar ist, wird mithilfe eines Ausnahmebehandlungsblocks gelöst.

Lassen Sie uns verstehen, was der Code hier tut.

Zuerst wird innerhalb des try-Blocks ein with-Block erstellt, der alle ausgegebenen Warnungen abfängt. Innerhalb dieses with-Blocks wird die warnings.simplefilter-Funktion verwendet, um dem urllib3-Untermodul InsecureRequestWarning einen ignore-Wert zuzuweisen.

Wie wir im Importabschnitt erfahren haben, löst das Untermodul InsecureRequestWarning eine Ausnahme für ablaufende SSL-Zertifikate aus; die Zuweisung eines Ignorieren-Werts umgeht die zweite verursachte Ausnahme.

try:
    with warnings.catch_warnings():
        warnings.simplefilter('ignore', InsecureRequestWarning)
        yield

Innerhalb des Blocks finally werden die ursprünglichen Einstellungen, die in old_merge_environment_settings gespeichert sind, der Funktion requests.Session.merge_environment_settings wieder zugewiesen.

Da alle geöffneten Adapter geschlossen werden müssen, bevor das Programm beendet wird, wird eine for-Schleife erstellt, die so oft wiederholt wird, wie oft geöffnete Adapter im Programm vorhanden sind.

Alle Adapter werden mit der Funktion adapter.close() mit einem try-except-Block geschlossen; innerhalb des außer-Blocks wird die Iteration übergeben.

for adapter in opened_adapters:
    try:
        adapter.close()
    except:
        pass

Der vollständige Code ist unten angegeben.

import warnings
import contextlib

import requests
from urllib3.exceptions import InsecureRequestWarning

old_merge_environment_settings = requests.Session.merge_environment_settings


@contextlib.contextmanager
def no_ssl_verification():
    opened_adapters = set()

    def merge_environment_settings(self, url, proxies, stream, verify, cert):

        opened_adapters.add(self.get_adapter(url))

        settings = old_merge_environment_settings(
            self, url, proxies, stream, verify, cert
        )
        settings["verify"] = False

        return settings

    requests.Session.merge_environment_settings = merge_environment_settings

    try:
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", InsecureRequestWarning)
            yield
    finally:
        requests.Session.merge_environment_settings = old_merge_environment_settings

        for adapter in opened_adapters:
            try:
                adapter.close()
            except:
                pass

Verwenden Sie Monkey Patch in Python

Der Monkey-Patch kann mit der Methode no_ssl_verification() aufgerufen werden. Jede Anfrage, die mit dieser Methode gesendet wird, folgt den Anweisungen des Affen-Patches und deaktiviert die Überprüfung von Sicherheitszertifikaten mit Anfragen.

Schauen wir uns ein Beispiel an.

Die Methode no_ssl_verification wird unter einem with-Block aufgerufen. Dies führt die Methode innerhalb des Blocks aus und schließt sich dann selbst, wenn der Compiler aus dem Block kommt.

Innerhalb des Blocks wird ein requests.get-Aufruf an die URL mit einem abgelaufenen SSL-Zertifikat gesendet. Mit den Standardeinstellungen hätte dies einen Ausnahmewurf verursacht, aber diesmal wird der requests.get-Aufruf erfolgreich gesendet.

Eine weitere Anfrage wird mit den requests gesendet, wobei das verify-Feld auf True gesetzt ist. Im Gegensatz zum Standardszenario wird diesmal keine Fehlerausnahme ausgelöst.

with no_ssl_verification():
    requests.get("https://expired-rsa-dv.ssl.com/")
    print("Modifications working Properly")

    requests.get("https://expired-rsa-dv.ssl.com/", verify=True)
    print("`Verify=true` has its meaning changed")

Ausgang:

Modifications working Properly

`Verify=true` has its meaning changed

Es wurde gesehen, dass Verify=False die Anweisungen hatte, den Patch mit den Standardeinstellungen zurückzusetzen. Wenn dieses Feld in requests.get() gesetzt wurde, wird der Monkey-Patch auf die Standardeinstellungen zurückgesetzt, wodurch Fehlerausnahmen ausgelöst werden können.

requests.get("https://expired-rsa-dv.ssl.com/", verify=False)
print("It resets back")

Ausgang:

connectionpool.py:1052: InsecureRequestWarning: Unverified HTTPS request is being made to host 'expired-rsa-dv.ssl.com'.
  InsecureRequestWarning,
It resets back

Das requests-Untermodul session kann auch mit dem Monkey-Patch verwendet werden.

In eine Variable namens session wird die Funktion requests.Session() geladen. Der Wert session.verify wird auf True gesetzt.

Innerhalb eines with-Blocks wird die session.get()-Funktion verwendet, um die get-Anforderung an die URL zu senden, und das verify-Feld wird auf True gesetzt. Eine print-Anweisung gibt eine Nachricht aus, wenn die Verbindung hergestellt wurde.

session = requests.Session()
session.verify = True

with no_ssl_verification():
    session.get("https://expired-rsa-dv.ssl.com/", verify=True)
    print("Works in Session")

Ausgang:

Works in Session

Wenn der Kontextmanager beendet wird, schließt dieser Code alle offenen Adapter, die eine gepatchte Anforderung verarbeiten. Da requests für jede Sitzung einen Verbindungspool verwaltet und die Zertifikatsvalidierung nur einmal pro Verbindung erfolgt, treten unerwartete Ereignisse wie die folgenden auf.

try:
    requests.get("https://expired-rsa-dv.ssl.com/", verify=False)
except requests.exceptions.SSLError:
    print("It breaks")

try:
    session.get("https://expired-rsa-dv.ssl.com/")
except requests.exceptions.SSLError:
    print("It breaks here again")

Ausgang:

C:\Users\Win 10\venv\lib\site-packages\urllib3\connectionpool.py:1052: InsecureRequestWarning: Unverified HTTPS request is being made to host 'expired-rsa-dv.ssl.com'.
  InsecureRequestWarning,
It breaks here again

Verwenden Sie urllib3, um Warnungen in Python zu deaktivieren

Wenn das Programm die Deaktivierung von Sicherheitszertifikatsprüfungen erfordert, ohne requests oder Monkey-Patching zu verwenden, bietet die Verwendung von urllib3 eine einfache Lösung.

Importieren Sie requests und urllib3 und importieren Sie aus urllib3 das Submodul InsecureRequestWarning. Die Warnung wird mit der Funktion urllib3.disable_warnings deaktiviert.

Die Anweisung requests.post() wird unter den Block try gestellt und das Feld verify auf False gesetzt. Dadurch wird die Sicherheitsprüfung für abgelaufene Sicherheitszertifikate deaktiviert.

Innerhalb des except-Blocks wird SSLError mit einer Fehlermeldung ausgelöst.

import requests
from urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)

try:
    requests.post(
        url="https://expired-rsa-dv.ssl.com/", data={"bar": "baz"}, verify=False
    )
    print("Connection made successfully")

except requests.exceptions.SSLError:
    print("Expired Certificate")

Ausgang:

Connection made successfully

Abschluss

Dieser Artikel erklärt verschiedene Methoden zum Deaktivieren von Sicherheitszertifikatsprüfungen mit Anfragen in Python. Der Leser kann durch den Artikel Sicherheitsüberprüfungen einfach deaktivieren.

Verwandter Artikel - Python Requests