badkeys

Unsichere kryptographische Schlüssel

Key

https://badkeys.info/

Hanno Böck

Public-Key-Kryptographie

🔑 Öffentlicher Schlüssel

🔑 Privater Schlüssel

Verschlüsselung (veraltet)

Verschlüsseln mit öffentlichem Schlüssel🔑

Entschlüsseln mit privatem Schlüssel🔑

Digitale Signaturen

Signieren mit privatem Schlüssel🔑

Prüfen mit öffentlichem Schlüssel🔑

Public-Key-Verfahren

  • RSA
  • ECDSA, Ed25519/Ed448 (elliptische Kurven)
  • ML-DSA, ML-KEM (Post-Quanten-Krypto)

Wo wird Public-Key-Kryptographie genutzt?

TLS, HTTPS, SSH, DKIM, DNSSEC, ...

Fahrkarten, E-Perso, Impfzertifikate, ...

Public-Key-Kryptographie ist nur sicher, wenn der private Schlüssel geheim ist

Sicherheitslücke in keypair / GitKraken (2021)

GitHub security update: revoking weakly-generated SSH keys

"There is no haveibeenpwned for public keys as far as I know"

("Es gibt soweit ich weiß kein haveibeenpwned für öffentliche Schlüssel")

user jornane on lobste.rs, 10/2021

haveibeenpwned für Public Keys?

Klingt nach einer guten Idee!

badkeys web screenshot

https://badkeys.info/

CVE-2008-0166

Debian OpenSSL

Debian-OpenSSL-Bug

Durch einen fehlerhaften Patch funktionierte der Zufallszahlengenerator nicht korrekt und verwendete lediglich die Prozess-ID (PID) als Zufallsquelle

Testen, ob Schlüssel für Debian-OpenSSL-Bug verwundbar ist

(vor badkeys)

  • Alte Skripte, die auf modernen Systemen nicht funktionieren
  • Unvollständige Sammlungen oder Hash-Listen von betroffenen Schlüsseln
  • Verwirrende, unvollständige oder falsche Informationen

Schlüsselvarianten Debian-OpenSSL-Bug

  • PID (0 bis 32768)
  • OpenSSL oder OpenSSH
  • CPU-Architektur
  • Schlüsselgröße
  • Ältere oder neuere Version des betroffenen OpenSSL-Pakets
  • Konfigurationsunterschiede
Let's Encrypt announcement key size

Let's Encrypt (2020)

ECDSA

An mehreren Stellen wird erwähnt, dass die betroffene OpenSSL-Version kein ECDSA unterstützt.

Das stimmt nicht!

Debian Weak Keys and ECDSA, Hanno Böck (2022)

Alle Varianten des Debian-OpenSSL-Bugs zu erkennen ist unpraktikabel, badkeys erkennt aber alle plausiblen Varianten

https://github.com/badkeys/debianopenssl

Warum redet der so viel über eine 17 Jahre alte Sicherheitslücke?

ssl.com incident 2000

Matt Palmer (2020)

DKIM

DomainKeys Identified Mail

DKIM E-Mail header

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hboeck.de; s=key1; t=1715197611; bh=Z9fPSuWvmaUL/fgn9g0k2ORYPJe3Y3Vc5NiKvQJXc2w=; h=Date:From:To:Subject:Message-ID:MIME-Version:Content-Type: Content-Transfer-Encoding; b=TNyZHQd[...]

TXT record key1._domainkey.hboeck.de

v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQE[...]

Scan von DKIM-Keys

Benötigt passende DKIM-Selektoren, extrahieren aus bestehenden Mails oder gängige Selektoren (key, dkim, ...) raten / bruteforce

DKIM Scan mit badkeys (2024)

0,24 % der gescannten DKIM-Records betroffen von Debian-OpenSSL-Bug (2024!)

Betroffene Hosts

@cisco.com, @oracle.com, @skype.net, @github.partners, @partner.crowdstrike.com, @partners.dropbox.com, @1password.com

Screenshot GMail BIMI

BIMI

Brand Indicators for Message Identification

💰💰💰

Screenshot GMail BIMI

Warum waren relativ viele DKIM-Setups von einem 16 Jahre alten Bug betroffen?

2006: Debian-OpenSSL-Paket mit Bug veröffentlicht

2007: RFC 4871 (DKIM)

2008: Debian-OpenSSL-Bug wird entdeckt und gefixt

Debian OpenSSL Bug und DKIM

https://16years.secvuln.info/

Mehr Infos und Vortragsvideo (MiniDebConf)

Fermat

Fermat-Angriff (1643)

RSA-Schlüssel

Öffentlicher Schlüssel: N, e

Privater Schlüssel: N, e, d, p, q, dP, dQ, invQ

Faktorisierung

N = p · q

N: Modulus (öffentlich), p/q: Primzahlen (privat)

N = p · q

Aus p oder q und dem öffentlichen Schlüssel kann man den gesamten private Schlüssel berechnen

Die Sicherheit von RSA hängt davon ab, dass Faktorisierung "schwierig" ist

Fermat-Faktorisierung

N = p · q

a: Mitte zwischen p und q

b: Abstand zwischen a und p/q

N = (a + b) · (a - b)

N = (a + b) · (a - b)

N = a² - b²

b² = a² - N

b² = a² - N

Wir raten Werte von a (Start: √N) und prüfen, ob das Resultat eine Quadratzahl ist

a = gmpy2.isqrt(n)
while not gmpy2.is_square(a**2 - n):
    a += 1
bsq = a**2 - n
b = gmpy2.isqrt(bsq)
p = a + b
q = a - b

Fermat-Faktorisierung ist schnell, wenn Primzahlen nah beieinander liegen

1993 - 1996

Rechtsextreme Bombenanschläge in Österreich

(Bajuwarischen Befreiungsarmee, Franz Fuchs)

Franz Fuchs RSA

Verschlüsselte Nachricht damals von Hans Dobbertin geknackt

Klaus Schmeh (2022)

Scan von TLS-Zertifikaten mit Fermat-Faktorisierung (2022)

CVE-2022-26320

Drucker von Canon und Fujifilm (TLS-Bibliothek von Rambus) erstellten verwundbare Zertifikate

Gemeinsame Primzahlen

N = p · q

Angenommen, wir haben zwei RSA-Keys mit einer gemeinsamen und einer unterschiedlichen Primzahl

N₁ = p₁ · q₁

N₂ = p₂ · q₁

Größter gemeinsamer Teiler

N₁ = p₁ · q₁      N₂ = p₂ · q₁

ggT(N₁, N₂) = q₁

BatchGCD

Größte gemeinsame Teiler von vielen Zahlen

2012 finden zwei Teams zahlreiche RSA-Schlüssel mit gemeinsamen Primfaktoren

(Open-Source Code von Nadia Heninger unter factorable.net)

Heninger et al, Usenix (2012)

Lenstra et al (2012)

Warum passiert sowas?

Die betroffenen Schlüssel wurden überwiegend auf Embedded-Geräten unter Linux erstellt

Zufallszahlengenerator des Betriebssystems

Tastatureingaben, Festplatten-Zugriffszeiten, etc., werden genutzt, um den Zufallszahlengenerator zu initialisieren

  1. Betriebssystem startet, Zufallszahlengenerator ist noch nicht sicher initialisiert
  2. Startskript erzeugt RSA-Schlüssel beim Booten
  3. Erste Primzahl wird erzeugt (unsicher, kann sich wiederholen)
  4. Betriebssystem sammelt weitere Zufallsdaten
  5. Zweite Primzahl wird erzeugt (sicher)

Nach dem Paper gab es zahlreiche Änderungen am Linux-Kernel, um derartige Szenarien zu vermeiden

Taiwain Citizen Digital Certificate

Taiwain Citizen Digital Certificate

Bernstein et al (2013)

Sichere, zufällige Primzahl?

c0000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000000000000000000002f9

c9242492249292499249492449242492 24929249924949244924249224929249 92494924492424922492924992494924 492424922492924992494924492424e5

BSI Common Criteria

BSI-zertifizierte Chipkarten

ROCA

Return of Coopersmith's Attack (2017)

ROCA

Sicherheitslücke in RSA-Chips von Infineon, Schlüssel lassen sich erkennen und (mit Aufwand) brechen

Wegen ROCA mussten in Estland Ausweise mit verwundbaren Chips ausgetauscht werden

Auch diese Chipkarten waren BSI-zertifiziert

badkeys-Fund

Zertifikate von Yahoo mit ROCA-Keys (Ausgestellt 2021)

Public Private Keys

Öffentliche private Schlüssel

Private key on GitHub

Private Schlüssel, die man auf öffentlichen Webseiten finden kann, sind nicht sicher!

Bubcon Messenger

Bubcon-Security: Just Another Nightmare (2016, Nexus, CCC Hannover)

beA - besonderes elektronisches Anwaltspostfach (2017)

beA

beA

Versuch 1: Von CA signiertes Zertifikat für bealocalhost.de mit Schlüssel in der Anwendung

beA

Versuch 2: Selbstsigniertes CA-Zertifikat mit Schlüssel in der Anwendung

Jenkins Docker-Images

Hardcodierter SSH-Host-Key (CVE-2025-32754, CVE-2025-32755)

https://www.treasury.go.ke/treasury.go.ke.key

(Gefunden mit Tool snallygaster)

Es gibt viele Arten von öffentlichen privaten Schlüsseln

  • Beispiele in Dokumentation
  • Test-Keys in Softwarepaketen
  • Geleakte Keys
  • Vorgenerierte Keys in Firmware-Images, Containern, VM-Images
  • Sicherheitslücken (Debian-OpenSSL-Bug, keypair-Bug)
  • ...

Fortinet / FortiGate

CVE-2022-40684

Authentication Bypass in FortiGate-Geräten

Bereits 2022 bekannt, dass diese aktiv ausgenutzt wurde

Januar 2025

~15.000 Konfigurationsdateien von FortiGate-Geräten werden auf BreachForums veröffentlicht

Diese Konfigurationsdateien enthalten private Schlüssel, allerdings sind diese mit einem Passwort verschlüsselt

Das Passwort ist auch in den Konfigurationsdateien, aber ebenfalls verschlüsselt

Das Schlüssel-Passwort wiederum war mit dem Passwort "Mary had a littl" verschlüsselt

FortiGate (2025)

Private Schlüssel für ~100 nach wie vor gültige TLS-Zertifikate und für ~300 ACME-Accounts (Let's Encrypt)

Vorfall war seit 2022 bekannt!

"Enterprise-Security"

OpenID Connect

https://example.com/.well-known/openid-configuration

JSON Web Key Öffentlich

{
"kty": "EC",
"crv": "P-256",
"x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
"y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM"
}

JSON Web Key Privat


{
"kty": "EC",
"crv": "P-256",
"x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
"y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
"d": "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE"
}

JSON Web Keys haben die Eigenschaft, dass das Format für private und öffentiche Schlüssel quasi identisch ist

Privater Schlüssel? Öffentlicher Schlüssel?

Kann man ja mal verwechseln....

OpenID-Konfigurationen mit privaten Schlüsseln, mit Beispiel-Keys, sowie mit 512-Bit-RSA-Schlüsseln

Github Secret Scanning

Github Secret Scanning

Technische Details zu badkeys

Verschiedene Arten von Tests

Algorithmische Erkennung (Fermat, ROCA)

Liste von bekannten, unsicheren Schlüsseln (Debian-OpenSSL-Bug, Beispiel-Keys)

Hybrid (gemeinsame Primzahlen)

Liste von unsicheren Schlüsseln

Hash des öffentlichen Schlüssels?

Möglich, aber nicht optimal.

Öffentlicher RSA-Schlüssel

N (Modulus), e (Exponent)

badkeys-Blockliste: Hash des Modulus N

Angenommen, wir haben zwei RSA Schlüssel mit identischem Modulus, aber unterschiedlichem Exponenten

Key 1: N₁, e₁     Key 2: N₁, e₂

Wenn ein privater Schlüssel bekannt ist, lässt sich der andere effizient berechnen

Beispiel: Debian-OpenSSL-Bug

Standardmäßig nutzt OpenSSL den Exponenten e=65537, aber eine Kommandozeilenoption erlaubt die Verwendung von e=3

Da badkeys nur den Modulus betrachtet, erkennt es derartige Keys automatisch

Elliptische Kurven

Es gibt verschiedene Möglichkeiten, öffentliche Schlüssel zu codieren (X/Y-Wert, X-Wert und Point Compression)

badkeys betrachtet bei elliptischen Kurven nur den X-wert und kann daher Details der Codierung ignorieren

badkeys in der Praxis

Demo Time!

badkeys installieren und vorbereiten


pip install badkeys

badkeys --update-bl-and-urls

badkeys Kommandozeile

Demo Time!

badkeys Erkennung

  • Fermat-Faktorisierung
  • Gemeinsame Primfaktoren
  • ROCA
  • Debian-OpenSSL-Bug
  • keypair-Bug
  • Zahlreiche öffentliche private Schlüssel

Open Source (MIT-Lizenz)

https://github.com/badkeys/badkeys

Zukunft

Ausweitung der erkannten kompromittierten Schlüssel

Regelmäßige Scans von DKIM, DNSSEC, TLS-Zertifikaten

(unterstützt von NGI0/NLnet)

Ideen? Sponsoring? Consulting?

Sprecht mich gerne an!

Key

https://badkeys.info/

Fragen?