Das Problem
Ein normaler String-Vergleich (===) bricht ab, sobald das erste falsche Zeichen gefunden wird. Ein Vergleich mit richtigem Präfix dauert minimal länger als einer mit komplett falschem String.
Die Attacke
Versuch "a..." → 0.50ms (sofort falsch) Versuch "B..." → 0.52ms (1. Zeichen stimmt!) Versuch "Bo..." → 0.54ms (2 Zeichen stimmen!) ... Character für Character den ganzen Key erraten
In der Praxis: Braucht tausende Requests pro Character und Netzwerk-Jitter erschwert die Messung. Trotzdem: Es ist ein bekannter Angriffsvektor, den man verhindern muss.
Die Lösung
// Borzsport _cors.js const provided = req.headers['x-api-key'] || ''; if (provided.length !== key.length) return false; return crypto.timingSafeEqual( Buffer.from(provided), Buffer.from(key) );
timingSafeEqual vergleicht immer alle Bytes, egal wie viele stimmen. Konstante Laufzeit = keine Information für den Angreifer.
Demo: Timing-Unterschied selbst testen
Schalte zwischen naivem === und timingSafeEqual um und beobachte den Unterschied:
INTERAKTIV
Timing-Attacke Demo
Beobachte den Unterschied in der Antwortzeit zwischen naivem und timing-safe Vergleich.
Secret: Borz***********(Tipp: Fang mit "Borz" an)
Kernaussagen
- Normaler
===Vergleich leakt Information über Zeitunterschiede crypto.timingSafeEqual()hat konstante Laufzeit- Längenvergleich vorab ist OK (Key-Länge ist typischerweise bekannt)
- Python-Äquivalent:
hmac.compare_digest()