Kevin Cranmer
Kevin Cranmer

Reputation: 195

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!

Upvotes: 3

Views: 1465

Answers (3)

Paul Draper
Paul Draper

Reputation: 83255

this is done so the subscriber is confident that the "body has not been tampered with"

More accurately, it is done so that the subscriber is confident that the publisher authored the body.

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?

The auth token is not sent, only the signature.

And then they can spoof the encryption with the secret they snagged.

The token is not being used for encryption.


This may be a little different than you normally think about things.

API consumers usually verify the identity of the API provider using TLS, which verifies the identity of the server to the client.

For webhooks, the API consumer is now the server and the API provider is the client. And while there is mutual TLS that could verify the identity of the client, it is typically not used or supported by a lot of infrastructure.

Therefore, some other mechanism is required to verify the client (API provider) to the server (API consumer).

Upvotes: 3

deceze
deceze

Reputation: 522091

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.

Upvotes: 3

cyanic
cyanic

Reputation: 333

The purpose of shared secrets is both parties know the secret ahead of time, so it is not sent (otherwise it's no longer secret). Using your Twilio example, I checked the documentation and it doesn't say anything about additional headers other than the signature, and none of the parameters are a token either, so the auth token you mentioned is not included. Instead, both ends know the auth token, and they use it to generate/verify the signature.

If someone was to intercept and modify the message, they would need to know the secret to resign the message for it to be valid, and unless one side leaks the secret, the secret will remain unknown, and any modified data cannot be validly signed. If a token was passed around, the attacker only needs to intercept one sample, and then would be free to generate their own messages with the valid token. This is obviously less secure.

As for SSL, sources can be spoofed, and unless a client certificate is provided (which Twilio does not), there is no way to ascertain who sent the request, so SSL itself does not provide authentication.

Upvotes: 0

Related Questions