Security Tip: Validate Your Webhooks!

[Tip#51] Just because your webhook endpoints aren't listed anywhere (are they?) doesn't mean someone won't find them, and send malicious payloads to your app! You need to validate your webhook payloads!

Security Tip: Validate Your Webhooks!

Webhooks are great!

You just create a route, wait for the provider to send through a useful payload, and then process it.

What could possibly go wrong?!

Ah, but how do you know the payload you've received has come from the actual webhook provider? Surely it must be real, right? I mean, it’s not as if you’ve got your webhook endpoints in your user documentation... right? So how is a hacker going to find your endpoints?

They are safe, right...?

Answer me this, who has webhooks that look like these:

/webhooks/<vendor>
/callbacks/<vendor>
/events/<vendor>
/api/webhooks/<vendor>
/api/callbacks/<vendor>
/api/events/<vendor>
/<vendor>/webhooks
/spark/webhook
...

Yeah, I thought so...

I’m sure you get the point: webhook endpoints are very predictable and easy to find. This makes them incredibly easy to spoof, since it’s trivial for an attacker to learn the expected format of a webhook payload, forge their own, and send it to your app to be processed.

This is why webhook providers (usually) include some method of validating the payload. This is typically done through something like a HMAC signature with a pre-shared key. The provider builds the payload, generates a predictable signature (hash) using HMAC, and sends both the payload and signature through to you. Your app can then generate it’s own HMAC from the received payload, and verify the generated signature matches the provided one. If they don’t match, the payload has been tampered with/forged, and can be ignored.

💡
HMAC → Hash-based Message Authentication Code. We looked at these when we learned about Signed URLs.

The best place to start with validating your webhooks is to check the dev/API documentation for your provider. They should have a section on Webhook Security that outlines the process they require. Some may include it automatically in their SDKs too, which makes the job easier for you.

Here are a couple I recently came across:

If you can’t find their webhook security instructions, ask their support for help, and considering finding a new provider if they don't have anything.

🤦
If they don’t care enough about security to provide a way to verify webhook payloads, you may find their security is lacking in other areas too…

If your provider doesn’t have a way to validate their webhooks…

  • They may provide IPs you can allow-list. While this is a relatively good security measure, IPs can still be spoofed with the right environment, so it shouldn’t be your only defence.
  • You could also add a random URL parameter (like a random 32-character string) you can confirm is present when receiving the webhook. This will prevent someone from guessing your endpoint, which is better than nothing, but anyone logging the requests will be able to see it.

If you found this security tip useful, subscribe to get weekly Security Tips straight to your inbox. Upgrade to a premium subscription for exclusive monthly In Depth articles, or drop a coin in the tip jar to show your support.

When was the last time you had a penetration test? Book a Laravel Security Audit and Penetration Test, or a budget-friendly Security Review!

You can also connect with me on Bluesky, or other socials, and check out Practical Laravel Security, my interactive course designed to boost your Laravel security skills.