Search code examples
securitywebhookshmac

Webhook Security - HMAC vs Token in Callback URL


When it comes to Webhook Security, I see the standard is using HMAC. Each party has an identical shared secret. The publisher encrypts his request body using the shared secret and puts the encrypted hash in the header of its webhook notification. The subscriber then encrypts the body with the shared secret and confirms that his hash matches the one provided from the publisher. From reading, I've learned that this is done so the subscriber is confident that the "body has not been tampered with".

My question is, how could the body be tampered with? Assuming we are all using HTTPS, wouldn't a hacker need to break SSL encryption to modify the body? Twilio uses the accounts Auth Token as a shared secret. But if a hacker is able to open up a request body and tamper with it, wouldn't they be able to grab the Auth Token as it's sent over for authorization? And then they can spoof the encryption with the secret they snagged.

So why go through the trouble of another layer of security instead of just having the subscriber use a callback URL that has the token in the URL path. The URL would be encrypted along with the body. I don't see how an attacker could abuse this approach.

Thank you!


Solution

  • how could the body be tampered with?

    It doesn't need to be. Your server accepts incoming HTTP(S) requests from anybody. HTTPS cannot guarantee the authenticity or identity of the sender, it only guarantees that the sender and receiver can exchange messages without a 3rd party intercepting them.

    * It is possible to use client certificates in addition to server certificates, so HTTPS could verify the identity of both ends to each other; it's just rarely used in practice unfortunately and can be somewhat tricky to set up correctly. Which is why this alternative scheme is usually preferred, as it's easier to implement in practice.

    So the problem an HMAC in a webhook header is trying to solve is to validate the identity of the sender, because presumably only the authentic sender (Twilio etc.) would know the secret with which the HMAC was created. It allows the receiver to disregard entirely random 3rd parties sending arbitrary messages.

    If a 3rd party intercepted the request, they could tamper with the body, but they could not generate a new correct HMAC, because they do not have access to the secret, because the secret is not part of the request.

    An alternative would of course be to whitelist a bunch of IP addresses from which you expect to receive the webhook; but this is inconvenient for the sending service, since they couldn't freely allocate their IPs according to their needs. It also has a slight chance of being vulnerable to various issues, where an attacker might be able to get (partial) control of an IP, without otherwise causing a security breach on the secret keys.