Neulich wurde ich auf eine Frage aufmerksam, die ich - sensibilisiert durch die hohe Anzahl von Vorträgen zum Thema "Validierung von Zertifikaten" auf der letzten DefCon - selber und näher untersuchen wollte: Werden elektronische Zertifikate programmiersprachen- und frameworkübergreifend identisch validiert oder existieren hier Unterschiede?
Das erste Szenario ist schnell umschrieben: Ein selbstsigniertes Zertifikat wird beim Aufbau einer TLS-Verbindung vom Server beim Client vorgezeigt. Dieser hat betreffendes Zertifikat zu seinem Truststore hinzugefügt. Die Gültigkeitsdauer des Zertifikats ist abgelaufen. Kommt die Verbindung zustande?
Wer sich den entsprechenden Abschnitt in RFC 5820 genau durchliest wird feststellen, dass es mit ein wenig geistiger Flexibilität so ist, dass man die Balidierungsvorschrift hier auf zwei verschiedene Arten auslegen kann: Das Zertifikat ist vertrauenswürdig, also muss es nicht hinsichtlich der Laufzeit validiert werden. Gleichzeitig ist es aber das letzte in der Kette und muss daher bezüglich der Laufzeit validiert werden.
Hmm - wie ist es richtig? Keiner weiß es. Da es sich hier um sicherheitsrelevante Dinge handelt, würde ich sagen, dass man bei mehreren Alternativen immer die stringenteste wählen sollte - damit würde in dem geschilderten Fall also keine Verbindung zustande kommen.
Probieren wir es in der Praxis aus, zeigt sich, dass sich in Java problemlos ein javax.net.ssl.SSLSocket öffnen lässt und mit dem Server kommuniziert werden kann. Das ändert sich erst, wenn man das Zertifikat mittels eines java.security.cert.CertPathValidator in der Geschmacksrichtung PKIX gesondert validiert.
OpenSSL hingegen und übrigens auch Python lehnen die Verbindung zu einem Server mit einem als vertrauenswürdig markierten, selbstsignierten und abgelaufenen Zertifikat jedoch standardmäßig ab.
Ein schönes Beispiel dafür, dass Validierung für elektronische Zertifikate kein Selbstläufer ist und auch nicht der Programmiersprache/ dem Framework überlassen bleiben sollte - man sollte zumindest selbst über alle Use Cases nachdenken und Tests dafür schreiben - und diese dann auch durchführen!
Ich bin übrigens nicht der Erste, der sich über das Verhalten von Java an der Stelle wundert - IBM hatte sogar mal - vielleicht ist das auch immer noch so - eine kommerzielle Java Laufzeitumgebung im Angebot, die genau an dieser Stelle vom offiziellen Java abwich und ebenfalls standardmäßig im geschilderten Szenario keine Verbindung zuließ.
Das zweite Szenario ist noch einfacher: Schwache Schlüssel. Ich habe aus diesem Projekt heraus ein Repository aufgesetzt, in dem eine Skriptsammlung alle möglichen Variationen von Zertifikaten aus einer nicht-trivialen Public Key Infrastructure (PKI) heraus erzeugt. Und hier zeigt sich ein zweiter Aspekt, bei dem sich verschieden Frameworks / Programiersprachen nicht einig sind: Eines der erzeugten Zertifikate wurde für ein Schlüsselpaar mit Schlüssellänge 1024 Bit erstellt. Nutzt man diese digitale Identität für einen TLS Server und verbindet sich mit Java (Version 17), so ist das Problemlos möglich - auch mit Anwendung des oben vorgestellten java.security.cert.CertPathValidator ändert sich daran nichts.
Python 3 in der Version 3.10.12 jedoch lehnt die Verbindung ab - mit der Meldung:
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: EE certificate key too weak (_ssl.c:1007)
Auch hieran zeigt sich, dass man seine Use Cases kennen und entsprechende automatisierte Tests dafür haben sollte um solche Probleme frühzeitig zu erkennen und korrekt auf Irregularitäten in den Zertifikaten eingehen zu können.
09.03.2024
Ich habe in einem früheren Artikel darauf hingewiesen, dass Java (17) und Python (3.10) sich bei der Validierung von x509-Zertifikaten ein wenig unterscheiden. Einer der Unterschiede ist die Schwelle, ab der Schlüssel wegen zu geringer Länge als unsicher bewertet und die damit verbundenen Zertifikate abgelehnt werden.
03.02.2024
Ich habe auch vergangenes Jahr wieder einen Vortrag zum 37c3 eingereicht, der aber leider nicht angenommen wurde...
Testdatengeneratoren als Microservices mit Docker
02.11.2019
Ich habe die verschiedenen Testdatengeneratoren mittels Microservices über HTTP zugänglich gemacht, um sie unabhängig von der verwendeten Programmiersprache und/ oder Version (Java 11) verwenden zu können.
Weiterlesen...Android Basteln C und C++ Chaos Datenbanken Docker dWb+ ESP Wifi Garten Geo Git(lab|hub) Go GUI Gui Hardware Java Jupyter Komponenten Links Linux Markdown Markup Music Numerik PKI-X.509-CA Python QBrowser Rants Raspi Revisited Security Software-Test sQLshell TeleGrafana Verschiedenes Video Virtualisierung Windows Upcoming...
Nachdem ich neulich auf einen sehr interessanten Link gestoßen war, habe ich mich dafür interessiert, ob es möglich wäre - und falls ja: wie einfach - GIF-Animationen aus Java heraus zu erzeugen - und zwar mit Bordmitelln und ohne Zuhilfenahme externer Biblioheken
Weiterlesen...Nach der letzten losen Zusammenstellung (für mich) interessanter Links aus den Tiefen des Internet von 2024 folgt hier gleich die nächste:
Weiterlesen...Nachdem es nun bereits seit einiger Zeit ein wenig stiller um meine diversen Generatoren für Testdaten geworden ist, habe ich über den Feiertag in Thüringen einen neuen begonnen.
Weiterlesen...Manche nennen es Blog, manche Web-Seite - ich schreibe hier hin und wieder über meine Erlebnisse, Rückschläge und Erleuchtungen bei meinen Hobbies.
Wer daran teilhaben und eventuell sogar davon profitieren möchte, muß damit leben, daß ich hin und wieder kleine Ausflüge in Bereiche mache, die nichts mit IT, Administration oder Softwareentwicklung zu tun haben.
Ich wünsche allen Lesern viel Spaß und hin und wieder einen kleinen AHA!-Effekt...
PS: Meine öffentlichen GitHub-Repositories findet man hier - meine öffentlichen GitLab-Repositories finden sich dagegen hier.