NymVPN prices are changing! Don't miss your last chance to get a 2-year plan as low as $2.39 / month.

Nym-Sicherheitsüberprüfung

Sicherheitsprüfung der Nym-Kernkomponenten

9 mins Lesen

Einführung

Im Juli 2021 wurde Nym einer Sicherheitsprüfung durch Jean-Philippe Aumasson, einen renommierten Sicherheitsexperten, unterzogen. Ziel war es, potenzielle Schwachstellen und Fehler im Nym-Quellcode zu identifizieren, wobei der Schwerpunkt auf Kryptografie, Codesicherheit und Protokollsicherheit lag. Ziel der Überprüfung war es, die Integrität und Robustheit des Systems sicherzustellen, wobei wesentliche Aspekte seiner Architektur und Implementierung berücksichtigt wurden. Den vollständigen Auditbericht finden Sie hier.

Zusammenfassung des Audits

Die Prüfung fand im Sommer 2021 statt. Der Umfang der Prüfung umfasste mehrere Repositorys des Nym-Projekts, darunter:

  • Das Haupt-Repository von Nym: nymtech/nym, das die Dienste „Mixnode“, „Gateway“ und „Validator“ implementiert.
  • Sphinx-Mixnet-Paketformat: nymtech/sphinx, wird von Mixnodes verwendet.
  • Coconut Threshold Blind Signature Protocol: nymtech/coconut, wird zur Ausstellung von Zugangsdaten verwendet.

Im Rahmen der Prüfung wurde die aktuellste Version des Codes im „develop“-Zweig überprüft, die aufgrund der rasanten Entwicklung des Projekts regelmäßig aktualisiert wurde. Das Nym-Team gewährte JP Aumasson uneingeschränkten Zugriff auf den Quellcode, detaillierte Projektspezifikationen, Forschungsarbeiten und begleitende Unterlagen.

Schwerpunkte der Prüfung

Die Prüfung konzentrierte sich auf drei Hauptbereiche: Codesicherheit, Kryptografie und Protokollentwurf. Die Prüfer haben den Quellcode von Nym gründlich untersucht, um Schwachstellen zu identifizieren, und dabei nach häufigen Problemen wie unsicheren Programmiermustern und falsch behandelten Fehlern gesucht. Besonderes Augenmerk wurde auf Speichersicherheit und die Vermeidung von Fallstricken wie Ganzzahlüberläufen gelegt.

Die kryptografische Überprüfung umfasste eine breite Palette von von Nym verwendeten Kernprimitiven, darunter AES-128-CTR, BLAKE2b, ChaCha, Ed25519 und andere. Ziel war es, die korrekte Implementierung dieser Algorithmen sicherzustellen und ihre Widerstandsfähigkeit gegenüber Seitenkanalangriffen, dem Missbrauch von Parametern und Schwachstellen bei der Zufallsgenerierung zu überprüfen.

Neben der Überprüfung der einzelnen Komponenten wurden im Rahmen des Audits auch die Protokolle untersucht, die die Kernfunktionalität von Nym definieren. Dazu wurden das Sphinx-Paketformat und das Coconut-Threshold-Blind-Signatur-Protokoll, um etwaige Schwachstellen zu identifizieren, die die Privatsphäre oder die Sicherheit gefährden könnten. Im Mittelpunkt der Überprüfung standen potenzielle Informationslecks, die die Anonymität der Nutzer gefährden, sowie Schwachstellen wie die Umgehung der MAC-Verifizierung, Angriffe auf kleine Untergruppen und Fehler in kryptografischen Operationen wie der BLS12-381-Arithmetik und Zero-Knowledge-Beweisen.

Übersicht über die Ergebnisse

Bei der Prüfung wurden neun Sicherheitslücken entdeckt. Keiner wurde als kritisch eingestuft, zwei als hoch, einer als mittel und sechs als gering. Darüber hinaus wurden 17 Beobachtungen gemacht, die Empfehlungen zur weiteren Stärkung des Nym-Netzwerks enthalten. Im Folgenden geben wir einen Überblick über die Korrekturen, die zur Behebung aller identifizierten Sicherheitslücken implementiert wurden.

S-SPHX-01: Fehlende Validierungen von Schlüsseln (gering)

Das in nymtech/sphinx festgestellte Problem hinsichtlich der unzureichenden Validierung privater und öffentlicher Schlüssel wurde durch die Migration zur x25519-Bibliothek behoben, die aufgrund ihres Aufbaus die Gültigkeit der Schlüssel von Natur aus sicherstellt. Die x25519-Implementierung stellt sicher, dass private Schlüssel korrekt begrenzt werden, d. h., sie werden automatisch auf eine gültige Teilmenge von Skalaren beschränkt, wodurch das Risiko der Verwendung ungültiger privater Schlüssel ausgeschlossen wird. Zudem validiert x25519 zwar öffentliche Schlüssel nicht explizit, doch seine Montgomery-Ladder-Implementierung verhindert von Natur aus, dass bestimmte ungültige Kurvenpunkte verwendet werden. Dadurch wird das Risiko gemindert, auf Punkte im Unendlichen oder andere fehlerhafte öffentliche Schlüssel zu stoßen. Darüber hinaus stellt der Schlüsselaustauschprozess sicher, dass ein gemeinsames Geheimnis, das ausschließlich aus Nullen besteht, erkannt und gegebenenfalls zurückgewiesen werden kann. Durch den Einsatz von x25519 haben wir die Schlüsselvalidierung erheblich verbessert und damit das Risiko verringert, dass ungültige oder falsch formatierte Schlüssel im System verwendet werden. Damit werden die im Audit geäußerten Bedenken hinsichtlich der Schlüsselvalidierung wirksam ausgeräumt.

S-COCO-01: Verteilung mit Hash-zu-Skalar-Verzerrung (Niedrig)

Der Hash-Prozess zur Ableitung eines Skalars im BLS12-381-Feld umfasste bisher die direkte Zuordnung der Ausgabe einer Hash-Funktion zu einem Element des Skalarfeldes. Dieser Ansatz führte jedoch aufgrund der modularen Reduktionsoperation (mod p) zu einer Verzerrung, die zu einer ungleichmäßigen Verteilung führen kann, wenn die Hash-Ausgabe nicht perfekt mit dem Primmodul des Feldes übereinstimmt. Um dieses Problem zu beheben, haben wir die bestehende Funktion „hash-to-scalar“ durch die Funktion [hash_to_field] ersetzt(https://github.com/jstuczyn/bls12_381/blob/22cd0a16b674af1629110a2dc8b6cf6c73ea4cd9/src/hash_to_curve/mod.rs#L44) aus dem bls12_381-Crate. Diese Funktion folgt der standardisierten Hash-to-Field-Spezifikation und gewährleistet eine einheitliche und unverzerrte Abbildung von Hash-Ausgaben auf Feldelemente. Darüber hinaus stützt sich auch das zk-Nym-Protokoll, das das Coconut-Protokoll abgelöst hat, bei seinen Hash-Operationen auf diese Funktion und gewährleistet so Konsistenz und Korrektheit bei kryptografischen Berechnungen.

S-COCO-02: Berechtigungen für Keygen-CLI-Schlüsseldateien (Niedrig)

Die Prüfer stellten fest, dass die keygen-cli-Schlüsseldateien Standardberechtigungen aufweisen, jedoch aus Sicherheitsgründen strengere Berechtigungen haben sollten. Dieses Problem erforderte keine Änderungen, da keygen-cli nur in den frühen Phasen unserer Coconut-Implementierung verwendet wurde. Es ist nicht mehr Teil des Haupt-Nym-Repositorys und wird nicht mehr aktiv genutzt. Da das Tool nicht mehr verwendet wird, waren keine weiteren Maßnahmen hinsichtlich seiner Dateiberechtigungen erforderlich.

S-CRYP-01: Mögliche Wiederverwendung des IV bei einer Stream-Verschlüsselung (Hoch)

Das Problem betrifft eine Funktion, die Daten mithilfe eines Initialisierungsvektors (IV) verschlüsselt. Wird kein IV angegeben, verwendet die Funktion standardmäßig einen IV von Null, was zu einer Wiederverwendung des IV führen könnte. Dieses Problem wurde durch die Einführung des AES-GCM-SIV-Protokolls während der Registrierungsphase behoben. Um Downgrade-Angriffe zu verhindern, haben wir die Option zur Verwendung des veralteten AES-128-CTR-Schlüssels für die Kommunikation zwischen Client und Gateway entfernt. Solange sowohl der Client als auch das Gateway auf dem neuesten Stand sind, generieren sie stets einen zufälligen IV-Wert ungleich Null.

S-PROT-01: Mögliche doppelte Verwendung von Anmeldedaten (Hoch)

Den Prüfern fiel auf, dass in der geprüften Version von Coconut ein Mechanismus zur Erkennung von Doppelausgaben fehlte, was dazu hätte führen können, dass mehrere Gateways eine Berechtigung gleichzeitig fälschlicherweise als ungenutzt validiert hätten. Der Coconut-Bandbreitenvertrag wurde jedoch später aktualisiert, um die Nutzung von Zugangsdaten durch die Speicherung des Status in der Blockchain zu verfolgen und dieses Problem zu beheben. Zudem wurde Coconut inzwischen durch das zk-nyms-Protokoll, das eine integrierte Funktion zur Erkennung von Doppelausgaben enthält.

S-NYM-01: Abhängigkeiten mit bekannten Sicherheitslücken (mittel)

Die Prüfer stellten fest, dass mehrere Komponenten des Nym-Projekts auf älteren Versionen von Abhängigkeiten beruhten, die bekannte Sicherheitslücken aufwiesen. So verwendete beispielsweise das Sphinx-Repository eine unsichere Version der Crate generic-array, das Nym-Kern-Repository stützte sich auf eine veraltete Version von tokio, und der Nym-Client enthielt mehrere Crates mit bekannten Sicherheitslücken, von denen einige im Nym-Kontext ausnutzbar zu sein schienen. Auf Empfehlung der Prüfer haben wir die Abhängigkeiten regelmäßig aktualisiert. Wir verwalten unsere Abhängigkeiten nun aktiv über Dependabot, das unsere Repositories kontinuierlich überwacht und veraltete oder anfällige Pakete automatisch erkennt. Siehe die laufend angewendeten Dependabot-Korrekturen in unserem Repository.

S-NYM-02: Fehler bei der Entschlüsselung nicht behandelt (Niedrig)

Das im Code festgestellte Problem tritt in der Funktion recover_identifier in der Datei nym/common/nymsphinx/acknowledgments/identifier.rs auf, wo Fehler bei der Entschlüsselung, wie z. B. ungültige Parameter, nicht ordnungsgemäß behandelt werden. Dies kann zu Panik oder anderen Zuständen der Unsicherheit führen. Ein ähnliches Problem tritt in der Funktion recover_plaintext in nym/common/nymsphinx/src/receiver.rs auf. Werden Entschlüsselungsfehler nicht korrekt behandelt, kann dies möglicherweise dazu führen, dass das System in einen instabilen oder unsicheren Zustand gerät. Nach sorgfältiger Prüfung der Funktionen sind wir zu dem Schluss gekommen, dass das erste angegebene Beispiel in recover_identifier kein Problem darstellt. Es ist unmöglich, falsche Parameter anzugeben, da alles mit AckEncryptionAlgorithm parametrisiert ist (Link), was bedeutet, dass ungültige Werte bereits zur Kompilierungszeit erkannt würden. Der zweite von ihnen erwähnte Fall, recover_plaintext, existiert nicht mehr. Der Code, der ihn ersetzte – recover_plaintext_from_regular_packet – wies jedoch einen theoretisch möglichen Fehlerfall auf, falls wir bestimmte Parameter auf ungewöhnliche Werte ändern würden. Wir haben dieses Problem durch das Hinzufügen einer ordnungsgemäßen Fehlerbehandlung hinzugefügt, um sicherzustellen, dass das System auch in Grenzfällen stabil bleibt.

S-NYM-03: Fehler bei der Generierung von Fragment-IDs (gering)

Der zur Generierung neuer Fragment-IDs verwendete Code wählt zufällig einen i32-Wert aus und ermittelt dessen Absolutwert. Dieser Ansatz kann jedoch in Fällen, in denen der zufällig gewählte Wert i32::MIN ist, zu Problemen führen, da sein Absolutwert nicht innerhalb der Grenzen eines i32 dargestellt werden kann. Dies führt aufgrund der Einschränkungen der 2-Komplement-Kodierung zu einem Fehler „Versuch der Negation mit Überlauf“. Wir stimmen zu, dass die Schwereeinstufung für dieses Problem zu niedrig angesetzt ist, da die Wahrscheinlichkeit, dass dieser Fall auftritt, bei etwa 1 zu 4 Milliarden liegt. Wir haben das Problem jedoch behoben, indem wir die vom Prüfer empfohlene Korrektur umgesetzt haben, um mögliche Panikzustände und unerwartete Abstürze zu verhindern, insbesondere wenn Millionen von Nutzern Tausende von Fragment-IDs generieren.

S-NYM-04: Mnemonik nicht auf Null gesetzt (Niedrig)

Das festgestellte Problem zeigte, dass die für die Verbindung mit dem nymd-Dienst verwendete BIP39-Mnemonik nach der Verwendung nicht auf Null gesetzt wurde, was dazu führte, dass mehrere Kopien der Mnemonik im Speicher verblieben. Dies erhöhte das Risiko einer Offenlegung, da Mnemoniken im Gedächtnis leichter zu identifizieren sind als reine kryptografische Schlüssel. Um dieses Problem zu beheben, haben wir mehrere Abhilfemaßnahmen umgesetzt. In den Rust-Komponenten haben wir die Crate zeroize integriert, um sicherzustellen, dass jeglicher Speicher, der die Mnemonik enthält, sicher gelöscht wird, sobald er den Gültigkeitsbereich verlässt. Da JavaScript eine Sprache mit automatischer Speicherbereinigung ist und keine direkte Kontrolle über die Speicherfreigabe bietet, haben wir einen anderen Ansatz gewählt, um Sicherheitsrisiken in der JavaScript-Laufzeitumgebung zu minimieren. Konkret haben wir das System so angepasst, dass die JavaScript-Laufzeit beendet wird, sobald die Mnemonik an die Rust-Schicht übergeben wurde. Dadurch wird sichergestellt, dass alle Instanzen der Mnemonik im JavaScript-Speicher beim Beenden der Laufzeit gelöscht werden. Die Mnemonik wird so früh wie möglich an Rust übergeben, wodurch ihre Präsenz in JavaScript reduziert wird. In Rust sorgt zeroize dafür, dass alle Instanzen der Mnemonik sicher gelöscht werden, sobald sie nicht mehr benötigt werden. Mit diesen Änderungen haben wir die Speicherbelegung der Mnemonik deutlich minimiert, wodurch das Risiko einer Offenlegung verringert und sichergestellt wird, dass sensible Daten sicher verwaltet und gelöscht werden.

Letzte Worte

Wir möchten uns bei JP Aumasson für sein Fachwissen und sein Engagement während des gesamten Prüfungsverfahrens bedanken. Wir schätzen zudem die Zusammenarbeit und die Professionalität, die sowohl in der Planungs- als auch in der Durchführungsphase des Audits zum Ausdruck kamen. Unser kontinuierliches Engagement für Sicherheit hat weiterhin höchste Priorität, und wir freuen uns auf die weitere Zusammenarbeit mit Sicherheitsexperten, um die höchsten Standards für unser Ökosystem aufrechtzuerhalten.

Teilen