HMAC — Wie Webhooks wissen, dass Sie nicht lügen
Jeder Server kann eine POST-Anfrage an Ihren Webhook-Endpunkt senden. HMAC-Unterschriften sind die Methode, mit der legitime Absender die Payload bestätigen und Sie diese überprüfen können.
Jedes Mal, wenn Stripe eine Karte belastet, sendet es eine Webhook-Nachricht. Jedes Mal, wenn GitHub einen Pull-Request zusammenführt, sendet es eine Webhook-Nachricht. Diese Plattformen senden POST-Anfragen an eine URL, die Sie ihnen gegeben haben — aber hier ist die unangenehme Wahrheit: Jeder andere kann eine POST-Anfrage an dieselbe URL senden.
Wie kann Ihr Server sicherstellen, dass die Anfrage tatsächlich von Stripe stammt und nicht von einem Angreifer, der Ihre Endpunkts-URL erraten hat? Die Antwort ist HMAC — und sobald Sie es verstehen, sehen Sie, warum es die Standardmethode in jeder ernsthaften API-Plattform ist.
Das Problem: Jeder kann eine POST-Anfrage an Ihren Endpunkt senden
Webhook-Endpunkte sind einfach URLs. Sie sind öffentlich erreichbar (sie müssen es sein, damit der Absender sie erreichen kann), und sie akzeptieren POST-Anfragen. Es gibt nichts, was einem böswilligen Nutzer verhindert, ein gefälschtes Payload zu erstellen und an Ihren Endpunkt zu senden.
Stellen Sie sich vor, dass Ihr Webhook-Handler dies tut, wenn er einen Ereignis empfängt:
if event["type"] == "payment.completed":
fulfill_order(event["data"]["order_id"])
Ein Angreifer, der Ihre Endpunkts-URL kennt, könnte eine falsche payment.completed Ereignis mit einer beliebigen Bestell-ID senden. Ohne Verifikation würde Ihr Server bestellte Bestellungen vollständig erfüllen, die nie bezahlt wurden.
Sie benötigen eine Methode, um sicherzustellen, dass das Payload von jemandem stammt, der ein Geheimnis teilt, das Sie beide kennen — ohne das Geheimnis in der Anfrage zu übertragen.
Was ist HMAC?
HMAC steht für Hash-basierte Nachrichtenauthentifizierungscode. Es ist eine Konstruktion, die eine kryptographische Hash-Funktion (normalerweise SHA-256) mit einem Geheimnis kombiniert, um eine Signatur zu erzeugen. Die Signatur beweist zwei Dinge:
- Authentizität — das Nachricht wurde von jemandem erstellt, der das Geheimnis besitzt
- Integrität — das Nachricht wurde während der Übertragung nicht geändert
Die zentrale Eigenschaft von HMAC: Ohne das Geheimnis können Sie keine gültige Signatur erzeugen. Und Sie können die Signatur nicht rückgängig machen, um das Geheimnis zu ermitteln. Es ist ein einseitiger Beweis.
HMAC im Vergleich zu einem einfachen Hash
Ein einfacher Hash (wie SHA-256) der Payload löst das Integritätsproblem, aber nicht die Authentizität. Ein Angreifer, der eine gültige Payload abfängt, kann den Hash einer geänderten Payload neu berechnen. HMAC mischt Ihr Geheimnis in alle Schritte des Hash-Prozesses ein, sodass ohne das Geheimnis keine übereinstimmende Signatur erzeugt werden kann, selbst wenn man genau den verwendeten Hash-Algorithmus kennt.
Wie HMAC-Webhooks funktionieren
Der Prozess besteht aus drei Schritten: Schlüsselaustausch, Signierung und Verifikation.
Schritt 1: Schlüsselaustausch (happens once)
Wenn Sie einen Webhook mit einer Plattform wie Stripe oder GitHub konfigurieren, erzeugen sie einen Webhook-Secret und zeigen es Ihnen einmal. Sie speichern es auf dem Serverseite (nie in Client-Code oder öffentlichen Repos). Das ist alles — das Geheimnis wird nie über das Netzwerk weitergeleitet.
Schritt 2: Der Absender signiert das Payload
Bevor der Webhook gesendet wird, berechnet die Plattform einen HMAC-Signatur über den rohen Anfragenkörper mit Ihrem gemeinsamen Geheimnis:
signature = HMAC-SHA256(secret_key, request_body)
Die Signatur wird dann an die Anfrage angehängt, normalerweise in einem Header wie X-Hub-Signature-256 (GitHub) oder Stripe-Signature (Stripe). Der rohe Payload reist im Körper unverändert.
Schritt 3: Sie verifizieren beim Empfang
Wenn Ihr Server den Webhook empfängt, berechnen Sie erneut den gleichen HMAC mit dem rohen Körper und Ihrem gespeicherten Geheimnis, und vergleichen Sie das Ergebnis mit der Signatur im Header. Wenn sie übereinstimmen, ist das Payload authentisch und unverändert. Wenn nicht, lehnen Sie es ab.
expected = HMAC-SHA256(your_secret, raw_body)
if not constant_time_equal(expected, header_signature):
return 401
Beachten konstante Zeitvergleich — wir kommen später darauf zurück, warum das wichtig ist.
Realwelt-Beispiele
Stripe
Stripe sendet einen Stripe-Signature Header, der eine Zeitstempel und eine oder mehrere Signatur enthält:
Stripe-Signature: t=1679000000,v1=abc123...,v0=oldformat...
Die Signatur wird über timestamp.payload (angehängt mit einem Punkt) berechnet. Die Einbeziehung des Zeitstempels ermöglicht Stripe, sich gegen Replay-Angriffe zu verteidigen — wenn ein Angreifer einen gültigen signierten Antrag abfängt und später erneut sendet, können Sie ihn abweisen, weil der Zeitstempel zu alt ist.
GitHub
GitHub sendet einen X-Hub-Signature-256 Header im Format sha256=<hex_digest>. Die Signatur ist der HMAC-SHA256 des rohen Körpers mit dem Webhook-Secret, das Sie in Ihren Repository-Einstellungen konfiguriert haben.
Shopify
Shopify verwendet einen X-Shopify-Hmac-Sha256 Header mit einer Base64-gecodierten HMAC-SHA256-Signatur — gleiches Konzept, andere Codierung.
Verifikation im Code
Hier ist, wie die Verifikation in drei gängigen Sprachen aussieht. Der Muster ist identisch — nur die Bibliotheken unterscheiden sich.
Python
import hmac
import hashlib
def verify_webhook(secret: str, payload: bytes, signature_header: str) -> bool:
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
received = signature_header.removeprefix("sha256=")
return hmac.compare_digest(expected, received)
Node.js
const crypto = require('crypto');
function verifyWebhook(secret, rawBody, signatureHeader) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
const received = signatureHeader.replace('sha256=', '');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(received)
);
}
PHP
function verifyWebhook(string $secret, string $rawBody, string $signatureHeader): bool {
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
return hash_equals($expected, $signatureHeader);
}
Fehler, die die Sicherheit brechen
1. Verwendung von == anstatt konstanter Zeitvergleich
Standardstring-Gleichheit (==, ===) kürzt sich sofort, sobald ein Unterschied gefunden wird. Dies erzeugt einen Zeitseitenkanal: Ein Angreifer kann messen, wie lange Ihr Server unterschiedliche Signatur abweist. Strings, die eine längere Präfix teilen, dauern etwas länger, um abgelehnt zu werden. Mit genügend Anfragen kann ein Angreifer dies nutzen, um ein gültiges Signature Byte für Byte zu rekonstruieren.
Verwenden Sie immer einen konstanten Zeitvergleich: hmac.compare_digest() in Python, crypto.timingSafeEqual() in Node.js, hash_equals() in PHP.
2. Parsen des Körpers vor der Verifikation
HMAC wird über die rohen Bytes des Anfragenkörpers berechnet. Wenn Sie zuerst die JSON parsen und dann erneut serialisieren, können Sie eine andere Bytefolge erhalten (verschiedene Schlüsselreihenfolge, Leerzeichen, Kodierung). Fangen Sie immer den rohen Körper vor dem Zugriff durch die Frameworks’ Body-Parser auf, und verifizieren Sie dann gegen diesen.
3. Keine Überprüfung von Replay-Angriffen
Ein gültig signierter Antrag ist gültig für immer — es sei denn, Sie prüfen den Zeitstempel. Wenn eine Plattform einen Zeitstempel in ihre Signaturmethode einbezieht (Stripe tut das; GitHub nicht), lehnen Sie Anfragen ab, bei denen der Zeitstempel älter als einige Minuten ist. Dies verhindert, dass ein Angreifer einen legitimen Antrag abfängt und erneut sendet.
4. Das Geheimnis direkt in der Quellcode zu hardcodieren
Webhook-Geheimnisse sollten in Umgebungsvariablen oder einem Secrets-Manager leben, nie in Versionskontrolle eingebunden. Ein ausgelieferter Geheimnis bedeutet, dass ein Angreifer jedes Payload für immer fälschen kann — bis Sie es rotieren.
Was HMAC nicht schützt
HMAC beweist, dass das Payload von jemandem mit dem Geheimnis signiert wurde. Es schützt jedoch nicht vor: nicht Ein kompromittierter Absender
- — wenn die Signaturinfrastruktur von Stripe kompromittiert wäre, hätten falsche Ereignisse immer noch gültige Signatur Replay-Angriffe
- — es sei denn, Sie überprüfen auch einen Zeitstempel oder einen Nonce Geheimhaltung
- — HMAC verschlüsselt nichts; der Payload reist im Klartext (obwohl HTTPS dies behandelt) Für die meisten Webhook-Integrationen reicht HMAC über HTTPS aus.
HMAC — Wie Webhooks wissen, dass Sie nicht lügen 2
Das könnte Ihnen auch gefallen
Erweiterungen installieren
IO-Tools zu Ihrem Lieblingsbrowser hinzufügen für sofortigen Zugriff und schnellere Suche
恵 Die Anzeigetafel ist eingetroffen!
Anzeigetafel ist eine unterhaltsame Möglichkeit, Ihre Spiele zu verfolgen. Alle Daten werden in Ihrem Browser gespeichert. Weitere Funktionen folgen in Kürze!
Unverzichtbare Tools
Alle Neuheiten
AlleAktualisieren: Unser neuestes Werkzeug wurde am 14. Juni 2026 hinzugefügt
