News for hackers. Stuff that matters.
Re:Collection of best practices for providing and consuming ... by cuu508 on Friday August 19, 2022 @03:01AM (#32518208)
There are some interesting attack vectors to be aware of if you run a service where users can define webhooks, and your service will will call the user-defined webhooks to notify about certain system events. In my case, a monitoring service which can send notifications by calling user-defined webhook.

* Timeouts: the user can set up a webhook receiver that takes very long to generate a response. Your service must be able to deal with that.

* Timeouts (slowloris): the webhook target could be sending back one byte at a time, with 1 second pauses inbetween. If you are using, say, the "requests" python library for making HTTP requests, the "timeout" parameter will not help here

* Private IPs and reserved IPs: you probably don't want users defining webhooks to http://127.0.0.1:<some-port> and probing your internal network. Remember about private IPv6 ranges too

* Domains that resolve to private IPs: attacker could set up foo.com which resolves to a private IP. It is not enough to just validate webhook URLs when users set them up.

* HTTP redirects to private IPs. If your HTTP client library follows HTTP redirects, the attacker can set up a webhook endpoint that redirects to a private IP. Again, it is not enough to validate the user-supplied URL.

* Excessive HTTP redirects. The attacker can set up a redirect loop - make sure this does not circumvent your timeout setting.

My current solution for all of the above is to use libcurl via pycurl. I wrote a wrapper that mimics requests API: https://github.com/healthchecks/healthchecks/blob/master/hc/... (may contain bugs, use at your own risk :-)

Re:Collection of best practices for providing and consuming ... by pyjug on Friday August 19, 2022 @10:07AM (#32521104)
>Domains that resolve to private IPs: attacker could set up foo.com which resolves to a private IP

There's a clever extension to this attack; a naive way to mitigate it is to do a DNS resolution first to verify it's not a private IP and then do the actual request. An attacker can simply return a public IP on the first DNS resolution (with a 0 TTY) and then return a private IP on the second. This is called a "TOCTOU" (time-of-check time-of-use) vulnerability. I've written about this and other security best practices on my blog here - https://www.ameyalokare.com/technology/webhooks/2021/05/03/s...

I've also built an egress proxy that prevents such attacks here - https://github.com/juggernaut/webhook-sentry

Same caveat applies, use at your own risk :-)

Re:Collection of best practices for providing and consuming ... by tasn on Friday August 19, 2022 @10:15AM (#32521213)
Yeah, resolving twice is a really bad idea. A good rule of thumb for security: if you think you have a clever hack (e.g. checking DNS twice as a workaround to not being able to patch DNS resolution), it probably isn't so clever as you think.
Re:Collection of best practices for providing and consuming ... by m3h on Friday August 19, 2022 @03:22AM (#32518343)
It seems like webhooks have enough corner cases for the sender to require a specialized tool to protect itself from malicious users and to stay performant.

Does anyone have suggestion for such tools/services that they might have used in production?

Re:Collection of best practices for providing and consuming ... by calyhre on Friday August 19, 2022 @03:46AM (#32518461)
At Slite, for all outgoing calls we use a sandboxed proxy. It has saved us a few times already. We detailed the trick in a blog post -> https://slite-tech-blog.ghost.io/anti-ssrf-solution/
Re:Collection of best practices for providing and consuming ... by freeqaz on Friday August 19, 2022 @06:56AM (#32519499)
This is the path I've seen be fairly robust at a few tech companies I've helped sort out this defense for. I've helped write libraries too but the proxy is the easiest approach when targeting many languages.
Re:Collection of best practices for providing and consuming ... by charcircuit on Friday August 19, 2022 @04:52AM (#32518792)
For half of those it's called a firewall and for the other half you should specify timeouts / max redirects.
Re:Collection of best practices for providing and consuming ... by rajamaka on Friday August 19, 2022 @09:02AM (#32520449)
Outgoing webhooks dispatched from a Lambda seemed to solve most of the above problems for us
Re:Collection of best practices for providing and consuming ... by tasn on Friday August 19, 2022 @02:29PM (#32524496)
Using lambda doesn't protect you against any of these.

Timeout attacks: instead of failing you'll now be just be paying through the nose. And also with enough scale you can hit lambda limits and fail.

SSRF: you are still as vulnerable unless the lambda is outside your VPC (but then it's the VPC that solved it, not the lambda).

Re:Collection of best practices for providing and consuming ... by spiffytech on Friday August 19, 2022 @07:28AM (#32519718)
Stripe built an OSS egress network proxy that prevents webhooks from reaching internal resources:

https://github.com/stripe/smokescreen

Re:Collection of best practices for providing and consuming ... by technion on Friday August 19, 2022 @08:12AM (#32520035)
Just adding to that - don't forget about users defining AWS metadata addresses for a webhook. Returning IAM data to them can be .. bad.
Re:Collection of best practices for providing and consuming ... by tasn on Friday August 19, 2022 @08:27AM (#32520138)
Those are all great points! At Svix (we do webhooks as a service), we disallow redirects because of what you mentioned above, and because it's also just bad for performance (for both sides) and is most likely a configuration error anyway.

Resolution and timeouts: the aiohttp library for Python is slightly better in terms of letting you configure these things, though it's better to just use a sending proxy that does it all for you and is also located in an isolated VPC to make sure that you're protected.

Re:Collection of best practices for providing and consuming ... by pyjug on Friday August 19, 2022 @10:11AM (#32521162)
Disallowing redirects altogether is probably too big of a hammer. There are legit reasons to use redirects (like migration to new versions). A limit to the number of redirects seems ideal -- that's what Twilio does, for example.
Re:Collection of best practices for providing and consuming ... by tasn on Friday August 19, 2022 @10:20AM (#32521289)
Migrating to a new service: you can just update the webhook URL. On the other hand, there are at least a couple of problems with allowing even one redirect: it opens a pandora's box of security implications, and it's a performance penalty that is paid both by the sender and the receiver on every webhook sent. Realistically, 3xx are most likely to be a mis-configurations (e.g. including a trailing slash where one shouldn't) so I think being noisy about it is a great idea.

Not saying that there aren't valid use-cases (e.g. maybe some sort of dynamic webhook receiving), I'm just saying that we made this choice given the above, and we would be willing to change it if it's ever a barrier for someone.

Re:Collection of best practices for providing and consuming ... by pyjug on Friday August 19, 2022 @10:38AM (#32521544)
>you can just update the webhook URL

Fair enough, but often consumers that use multiple vendors receive webhooks in the same service; think about going from /v1/webhooks -> /v2/webhooks, they'd have to change the URL for every vendor. Easier to redirect first then update the URLs later. I think it's a reasonable expectation that a HTTP client would honor redirects as long as the usage isn't malicious (like loops etc)

Re:Collection of best practices for providing and consuming ... by gz5 on Friday August 19, 2022 @10:33AM (#32521471)
Great list. Closing layer 3* access (inbound firewall rule of deny-all) helps mitigate against the common webhook attack vectors as well (should still do all the L7 mitigation and best practices alluded to above for a multi-layered approach).

* examples:

https://netfoundry.io/zero-trust-webhook-security/ (blog)

https://youtu.be/TWohosldLP4 (video specifically for a Lambda function)

Re:Collection of best practices for providing and consuming ... by sudobinbash on Friday August 19, 2022 @09:40AM (#32520806)
Some webhook providers implement one-time verifications, CRCs, and heartbeat checks to address some of these problems:

https://webhooks.fyi/security/one-time-verification-challeng... https://webhooks.fyi/ops-experience/resiliency

Some also don't follow 301s or 302s and will process only specific http responses.

Re:Collection of best practices for providing and consuming ... by caseysoftware on Friday August 19, 2022 @09:17AM (#32520597)
Hello all! I'm one of the creators of webhooks.fyi over at https://ngrok.com/

Happy to answer any questions!

First, we started this project when we launched in-product webhook verification. We realized that we were collecting great information, had uncovered some clear and obvious patterns (both good & bad), and knew we could publish the results to help the ecosystem as a whole.

Next, yes it's ridiculously hard to build webhooks correctly. There are so many shortcuts that feel "okay" and you don't really think about until you realize that it didn't quite work as you had planned and now you have a gap. We're hoping the site can help people move more of that thinking earlier and make better decisions.

Finally, we're missing a bunch of webhooks! While we looked at 100+ in our own research, we only had time to add ~50 to this initial pass. If you'd like to add your favorites, pull requests welcome: https://github.com/ngrok/webhooks.fyi

And yes, seriously, you can use ngrok to verify webhooks pretty easily:

ngrok http 80 --verify-webhook=slack --verify-webhook-secret=[secret]

Re:Collection of best practices for providing and consuming ... by tasn on Friday August 19, 2022 @09:43AM (#32520847)
Oh, I didn't know about the new --verify-webhook addition to ngrok, that's cool!

Who can I chat with about adding Svix style webhooks[1] to ngrok? We do webhook sending as a service and power the webhooks for many companies, including one of the only three that got a "perfect score" on your list.

Adding Svix will make ngrok automatically support many webhooks services. I'd be happy to chat further my email is my name at the domain of the Svix service.

[1] https://docs.svix.com/receiving/verifying-payloads/how-manua...

Re:Collection of best practices for providing and consuming ... by sparsely on Friday August 19, 2022 @04:01AM (#32518520)
As this page makes very clear, it's actually pretty hard to make a robust webhooks implementation!

What alternatives are there? I've looked at: * Publishing AWS EventBridge events to other accounts. * /events instead of webhooks https://blog.sequin.io/events-not-webhooks/ * ???

Re:Collection of best practices for providing and consuming ... by floucky on Friday August 19, 2022 @04:13AM (#32518587)
Emails maybe ? But it means you have to regularly check your inbox. Or use a webhook called by your email provider when you receive an email :D
Re:Collection of best practices for providing and consuming ... by tasn on Friday August 19, 2022 @08:09AM (#32520006)
We built Svix[1] exactly for this reason. We make it super easy for companies to send webhooks reliably. There are only three companies with a "perfect score" on webhooks.fyi's list, we power one of them. ;)

[1] https://www.svix.com

Re:Collection of best practices for providing and consuming ... by caseysoftware on Friday August 19, 2022 @09:41AM (#32520814)
That's awesome and glad to see others making it easier and better to do this right.

Obviously you should add some of your other customers to make sure they get the attention they deserve.

Also, there are other patterns or practices that should be in the list, let us know. PRs are welcome but feel free to email me directly: [email protected]

Re:Collection of best practices for providing and consuming ... by tasn on Friday August 19, 2022 @09:46AM (#32520880)
Will email you now in a bit! I also just replied to your other comment about another topic, so there's much to discuss. :)
Re:Collection of best practices for providing and consuming ... by Traubenfuchs on Friday August 19, 2022 @11:43AM (#32522427)
> What alternatives are there?

At the top of my head: Short Polling, long polling, websockets, response streaming, SSE, SNS, paging API, comet...

Re:Collection of best practices for providing and consuming ... by leetrout on Friday August 19, 2022 @03:41PM (#32525219)
This is a fantastic resource! Thank you to the folks at ngrok for putting this together! As this site makes clear: webhooks are harder than they appear. Even just consuming webhooks it's easy to get bogged down dealing with issues around rate limits or recovering from bugs that cause missed events! Missed events being particularly painful with platforms that don't offer replay / retry.

Disclaimer: I work at https://hookdeck.com/ & I shamelessly plug our tool for giving you an awesome developer experience working with webhooks and helping deal with some of the concerns brought up on webhooks.fyi.

And if you are interested in webhooks at large a couple more resources worth checking out is the awesome-webhooks[1] list and the r/webhooks[2] subreddit (I just got ownership of the sub and started dusting it off this week after being neglected for the past few years! Please, come join!)

[1] https://github.com/realadeel/awesome-webhooks

[2] https://www.reddit.com/r/webhooks/

Re:Collection of best practices for providing and consuming ... by dgudkov on Friday August 19, 2022 @09:57AM (#32521002)
If only there was a single standard for webhook subscription verification. Cloud services invent their own authentication protocols. Webhook verification in Dropbox is different from that in Trello. The lack of a single standard makes it hard to design a universal incoming webhook service (we faced this problem).
Re:Collection of best practices for providing and consuming ... by tasn on Friday August 19, 2022 @10:02AM (#32521048)
Amen. FWIW, we are open source, and we publish libraries that let anyone sign and verify webhooks, hoping to save people the work and have a unified standard.

Libs: https://github.com/svix/svix-webhooks

Docs: https://docs.svix.com/receiving/verifying-payloads/how-manua...

The docs mention `Svix-Signature`, but we (and the libs) also support `Webhooks-Signature` which are useful for the generic standard.

The fact that we don't have REST for webhooks is both silly and annoying. Especially since (as you can see on the list in the original post) many companies who implement webhooks end up doing it poorly.

Re:Collection of best practices for providing and consuming ... by leetrout on Friday August 19, 2022 @03:24PM (#32525052)
One option is to use a platform like we created at https://hookdeck.com/ where we handle verification with multiple providers and then offer downstream destinations a verifiable request (the Hookdeck signature is a SHA-256 based HMAC digest).

Drop Hookdeck in as a proxy between the origin service and your destination and you get seamless integrations that help with reliability, observability, and recovery (request replays).

Re:Collection of best practices for providing and consuming ... by caseysoftware on Friday August 19, 2022 @10:09AM (#32521127)
I love the idea of a standard but it gets colorful as you start digging in what the individual leaders are doing.

On the signature front, there's this but it's not enough: https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-mes...

Re:Collection of best practices for providing and consuming ... by danpalmer on Friday August 19, 2022 @08:17AM (#32520065)
Great resource! I’ve encountered most of these problems at some point.

It would be great to see advice about implementations. Things like when to process in a queue and when not to, tying idempotency tokens to database transactions, etc. These are subtle issues, but when done well can help make very robust systems.

Re:Collection of best practices for providing and consuming ... by tasn on Friday August 19, 2022 @08:47AM (#32520310)
I recorded a video with advice about designing a webhooks system a couple of months ago: https://www.svix.com/blog/webhook-architecture-design/

It's high level, so it doesn't touch everything you mentioned, but it's a good primer.

Re:Collection of best practices for providing and consuming ... by egorfine on Friday August 19, 2022 @08:08AM (#32519992)
Excellent. I'm in process of building a service delivering notifications via webhooks right now. Thank you!
Re:Collection of best practices for providing and consuming ... by tasn on Friday August 19, 2022 @08:12AM (#32520037)
Shameless plug: we make it super easy for companies to send webhooks. https://www.svix.com

There are only 3 companies on webhooks.fyi's list with 3 green checks, and we're powering webhooks for one of those. :)

Re:Collection of best practices for providing and consuming ... by egorfine on Friday August 19, 2022 @08:30AM (#32520158)
Thank you!

Looks promising!

Re:Collection of best practices for providing and consuming ... by babbledabbler on Friday August 19, 2022 @10:06AM (#32521097)
Seeing this right after finishing a webhook integration.
Re:Collection of best practices for providing and consuming ... by Traubenfuchs on Friday August 19, 2022 @02:40AM (#32518111)
Why are callback registration and async APIs now called webhooks?
Re:Collection of best practices for providing and consuming ... by pavlov on Friday August 19, 2022 @02:55AM (#32518186)
The usual nomenclature is that regular callbacks and async API calls are made and registered in the same process space as the caller. (E.g. passing a function pointer in C, or using “await” in modern languages.)

Webhooks are callbacks received over HTTP from a public API. They may not be programmatically registered at all, e.g. the callback URL may be configured manually in an admin dashboard. So the application has less control over webhooks vs. regular callbacks or async functions.

Re:Collection of best practices for providing and consuming ... by osullip on Friday August 19, 2022 @02:54AM (#32518180)
Not sure of the evolution, but maybe because 'callbacks' exist everywhere, but 'webhooks' are specific to REST APIs.