it-swarm.com.de

Warum kann Ruby ein SSL-Zertifikat nicht überprüfen?

Zum ersten Mal habe ich versucht, die XMLRPC :: Client-Bibliothek für die Interaktion mit einer Remote-API zu verwenden. Ich erhalte diesen Fehler weiterhin:

warning: peer certificate won't be verified in this SSL session

Ich habe viele Leute gefunden, die diesen Fehler gefunden haben. Normalerweise handelt es sich dabei um selbstsignierte Zertifikate. Sie möchten nur, dass das Zertifikat entfernt wird. Sie machen also einen schmutzigen Affen-Patch, wie XMLRPC :: Client ihre http-Sitzung öffnet.

Ich ging zunächst davon aus, dass es dem Kunden einfach egal war, ob das Zertifikat gültig war oder nicht, also setzte ich meine Suche fort und stieß auf dieses Juwel . Es erzwingt einfach die Überprüfung aller SSL-Zertifikate und wirft einen schwerwiegenden Fehler aus, wenn dies nicht möglich ist. Genau das wollte ich. Ich habe es hinzugefügt, den Code erneut ausgeführt und jetzt bekomme ich Folgendes:

OpenSSL:SSL::SSLError:
  SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B:
  certificate verify failed

Na sicher! Das Zertifikat ist schlecht! Ich überprüfe aber genau, ob es mit openssls eingebautem s_client so aussieht:

openssl s_client -connect sub.example.com:443

und was bekomme ich:

CONNECTED(00000003)
---
Certificate chain
<snip>
Verify return code: 0 (ok)

Nun kommen wir zu meiner Frage. OpenSSL (die Befehlszeilenversion) gibt an, dass das Zertifikat in Ordnung ist. OpenSSL (die Ruby-Bibliothek) ist anderer Meinung. Alle meine Webbrowser sagen, dass das Zertifikat gut ist.

Einige zusätzliche Details, die nützlich sein könnten. Das Zertifikat ist ein Platzhalter, ist jedoch für die Domäne gültig. Der openssl s_client wurde auf dem gleichen Computer Sekunden vom Ruby-Code ausgeführt. Dies ist Ruby 1.8.7 p357, das mit RVM installiert wird.

Verwendet Ruby etwas anderes als das CA-Paket, das vom Host-Betriebssystem bereitgestellt wird? Gibt es eine Möglichkeit, Ruby mitzuteilen, ein bestimmtes CA-Paket oder das System zu verwenden?

53
Sam Stelfox

Wenn Sie nur daran interessiert sind, wie Ruby sich wie OpenSSL s_client verhält, oder wenn Ihr Browser dies tut, können Sie zum letzten Abschnitt springen. Ich werde das Kleingedruckte im Folgenden behandeln.

Standardmäßig verwendet der für die Verbindung verwendete OpenSSL::X509::Store keine vertrauenswürdigen Zertifikate. Aufgrund Ihrer Kenntnisse der Anwendungsdomäne würden Sie normalerweise eine Instanz von X509::Store mit den vertrauenswürdigen Zertifikaten füttern, die für Ihre Anwendung relevant sind. Dafür gibt es mehrere Möglichkeiten:

  • Store # add_file nimmt einen Pfad zu einem PEM/DER-codierten Zertifikat
  • Store # add_cert benötigt eine Instanz von X509 :: Certificate
  • Store # add_path nimmt einen Pfad zu einem Verzeichnis, in dem vertrauenswürdige Zertifikate gefunden werden können 

Der "Browser" -Ansatz

Dies ist im Gegensatz zu den Ansatzbrowsern Java (cacerts) oder Windows mit eigenem internem Speicher für vertrauenswürdige Zertifikate, zu nehmen. Dort ist die Software mit einer Reihe von vertrauenswürdigen Zertifikaten ausgestattet, die nach Ansicht des Softwareherstellers als "gut" eingestuft werden. Im Allgemeinen ist dies keine schlechte Idee, aber wenn Sie tatsächlich in diese Sets schauen, werden Sie bald feststellen, dass es einfach zu viele Zertifikate gibt. Eine Einzelperson kann nicht wirklich sagen, ob all dieser Zertifikate blind vertraut werden sollte oder nicht. 

Der Ruby-Ansatz

Die Anforderungen Ihrer typischen Ruby-Anwendung unterscheiden sich dagegen erheblich von denen eines Browsers. Ein Browser muss in der Lage sein, zu einer "legitimen" Website zu navigieren, die über ein TLS-Zertifikat verfügt und über https bereitgestellt wird. In einer typischen Ruby-Anwendung müssen Sie sich jedoch nur mit wenigen Diensten befassen, die TLS verwenden oder die Zertifikatsüberprüfung sonst erforderlich machen würden. 

Der Ruby-Ansatz bietet den Vorteil - obwohl er mehr Handarbeit erfordert, erhalten Sie eine handgefertigte Lösung, die genau auf die Zertifikate vertraut, die in Ihrem jeweiligen Anwendungskontext vertrauen sollten. Dies ist langwierig, aber die Sicherheit ist auf diese Weise viel höher, da Sie weniger Angriffsfläche zeigen. Nehmen Sie die jüngsten Ereignisse an: Wenn Sie nie DigiNotar oder einen anderen gefährdeten Root-Server in Ihr Vertrauensset aufnehmen mussten, besteht keine Möglichkeit, dass solche Verstöße Sie betreffen.

Der Nachteil dabei ist jedoch, wie Sie bereits festgestellt haben, dass die OpenSSL-Erweiterung standardmäßig kein any Peer-Zertifikat validieren kann, wenn Sie keine vertrauenswürdigen Zertifikate aktiv hinzufügen. Damit alles funktioniert, müssen Sie die Konfiguration manuell einrichten. 

Diese Unannehmlichkeiten haben zu einer Reihe zweifelhafter Maßnahmen geführt, um diese zu umgehen. Das Schlimmste ist, dass OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE global festgelegt wurde. Bitte mach das nicht. Wir haben sogar Witze über das Hinzufügen von Code gemacht, durch den Ihre Anwendung zufällig abstürzt, wenn wir auf diesen Hack stoßen :)

Wenn das manuelle Einrichten des Vertrauens zu kompliziert erscheint, biete ich jetzt eine einfache Alternative an, die dazu führt, dass sich die OpenSSL-Erweiterung genau wie OpenSSL-CLI-Befehle wie s_client verhält.

Warum kann s_client das Zertifikat überprüfen?

OpenSSL verwendet einen ähnlichen Ansatz wie Browser und Windows. Bei einer typischen Installation wird ein Bündel vertrauenswürdiger Zertifikate irgendwo auf Ihrer Festplatte abgelegt (z. B. /etc/ssl/certs/ca-bundle.crt). Dies wird als Standardsatz vertrauenswürdiger Zertifikate verwendet. Dort sieht s_client aus, wenn Peer-Zertifikate überprüft werden müssen. Deshalb hat Ihr Experiment erfolgreich abgeschlossen.

Ruby wie s_client verhalten lassen

Wenn Sie bei der Validierung von Zertifikaten mit Ruby immer noch denselben Komfort wünschen, können Sie das OpenSSL-Paket vertrauenswürdiger Zertifikate verwenden, sofern auf Ihrem System verfügbar, indem Sie OpenSSL::X509::Store#set_default_paths aufrufen. Weitere Informationen finden Sie hier . Um dies mit XMLRPC::Client zu verwenden, stellen Sie sicher, dass set_default_paths für den verwendeten X509::Store aufgerufen wird.

110
emboss

Wenn Sie eine CA-Zertifikate-Datei haben, tun Sie dies einfach:

http.ca_file = <YOUR CA-CERT FILE PATH>
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.verify_depth = 5
0
Guihen