
# Technischer Bericht zu CVE-2026-26717: HMAC-Timing-Angriff in der Webhook-Authentifizierung von OpenFUN Richie LMS ## Übersicht CVE-2026-26717 ist eine Schwachstelle in der Webhook-Authentifizierung von OpenFUN Richie LMS, die einen HMAC-Timing-Angriff ermöglicht. Ein Angreifer kann durch präzise Zeitmessungen der Antwortzeiten den gültigen HMAC-Signaturwert schrittweise erraten und so unbefugten Zugriff auf geschützte Webhook-Endpunkte erlangen. ## Betroffene Komponente Die Schwachstelle befindet sich in der Webhook-Authentifizierungslogik, die eingehende Webhook-Anfragen anhand einer HMAC-Signatur validiert. Die fehlerhafte Implementierung verwendet einen nicht konstanten Zeitvergleich, wodurch Informationen über die Korrektheit einzelner Bytes der Signatur preisgegeben werden. ## Verwundbarer Code Der folgende Codeausschnitt zeigt die anfällige Implementierung: ```python import hmac import hashlib def verify_webhook_signature(payload, signature, secret): expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest() # Unsicher: Nicht-konstanter Zeitvergleich return expected == signature ``` Das Problem liegt in der Verwendung des normalen Gleichheitsoperators (`==`), der einen Byte-für-Byte-Vergleich durchführt und bei der ersten Abweichung abbricht. Dadurch entsteht eine messbare Zeitdifferenz zwischen teilweise korrekten und vollständig falschen Signaturen. ## Auswirkungen Ein Angreifer kann diese Timing-Seitenkanalinformationen ausnutzen, um: - Die gültige HMAC-Signatur Byte für Byte zu rekonstruieren - Authentifizierte Webhook-Anfragen zu fälschen - Auf geschützte Funktionen wie Kurserstellung, Benutzerverwaltung oder Zahlungsbenachrichtigungen zuzugreifen - Die Integrität des LMS-Systems zu kompromittieren Der Angriff erfordert wiederholte Anfragen mit manipulierten Signaturen und präzise Zeitmessungen, ist aber mit modernen Tools und ausreichend vielen Messungen praktisch durchführbar. ## Empfohlener Fix Die Schwachstelle wird durch die Verwendung von `hmac.compare_digest` behoben, das einen konstanten Zeitvergleich durchführt: ```python import hmac import hashlib def verify_webhook_signature(payload, signature, secret): expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest() # Sicher: Konstanter Zeitvergleich return hmac.compare_digest(expected, signature) ``` `hmac.compare_digest` stellt sicher, dass der Vergleich unabhängig von der Position der ersten Abweichung immer die gleiche Zeit benötigt, wodurch der Timing-Seitenkanal eliminiert wird. ## Zusätzliche Empfehlungen - Verwenden Sie ausschließlich `hmac.compare_digest` für alle Signaturvergleiche - Implementieren Sie Ratenbegrenzung für Webhook-Endpunkte - Überwachen Sie verdächtige Anfragemuster - Aktualisieren Sie OpenFUN Richie LMS auf die neueste gepatchte Version ## Fazit CVE-2026-26717 unterstreicht die Bedeutung konstanter Zeitvergleiche bei der Authentifizierung. Die einfache Umstellung auf `hmac.compare_digest` schließt die Schwachstelle vollständig und verhindert Timing-Angriffe auf die Webhook-Signaturprüfung.
Autor: Elvin Latifli
CVE-ID: CVE-2026-26717
Schweregrad: Mittel (CVSS 3.1: 4.8 — AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N)
Betroffenes Produkt: OpenFUN Richie (alle Versionen vor Commit a1b5bbd)
Betroffene Komponente: src/richie/apps/courses/api.py — sync_course_runs_from_request
Fix-Commit: a1b5bbda
Richie ist ein Open-Source-CMS, das von France Université Numérique (OpenFUN) entwickelt wurde und auf DjangoCMS basiert. Es wurde entwickelt, um Organisationen beim Aufbau vollwertiger Online-Bildungsportale mit Kurskatalogen zu unterstützen, die mit Learning-Management-Systemen (LMS) wie OpenEdX synchronisiert werden. Richie übernimmt die Synchronisierung von Kursdaten über authentifizierte Webhooks — einer davon enthielt die in diesem Bericht beschriebene Schwachstelle.
Der Webhook-Endpunkt sync_course_runs_from_request verwendete den Standard-Operator ==, um den eingehenden Authorization-Header mit der erwarteten HMAC-Signatur zu vergleichen:
# VERWUNDBAR
signature_is_valid = any(
authorization_header == get_signature(message, secret)
for secret in getattr(settings, "RICHIE_COURSE_RUN_SYNC_SECRETS", [])
)
Der Operator == führt einen Vergleich ohne konstante Laufzeit durch — er bricht ab, sobald das erste nicht übereinstimmende Zeichen gefunden wird. Durch das Senden vieler präparierter Anfragen und das Messen von Antwortzeitunterschieden kann ein entfernter Angreifer die korrekte Signatur Zeichen für Zeichen ableiten und letztendlich ein gültiges Authentifizierungstoken fälschen, wodurch die Authentifizierung des Webhooks vollständig umgangen wird.
Ein erfolgreicher Angriff ermöglicht es einem nicht authentifizierten entfernten Angreifer:
Der Fix ersetzt == durch Pythons hmac.compare_digest(), das für Vergleiche mit konstanter Laufzeit entwickelt wurde und den Timing-Seitenkanal eliminiert:
# BEHOBEN
signature_is_valid = any(
hmac.compare_digest(authorization_header, get_signature(message, secret))
for secret in getattr(settings, "RICHIE_COURSE_RUN_SYNC_SECRETS", [])
)