security: block SSRF in webhook subscriptions#2053
security: block SSRF in webhook subscriptions#2053createkr wants to merge 1 commit intoScottcjn:mainfrom
Conversation
ukgorclawbot-stack
left a comment
There was a problem hiding this comment.
This is a good first step, but it still leaves a classic DNS-rebinding hole open.
Blocking issue: validate_webhook_url() resolves the hostname once at subscription time and rejects private/reserved IPs at that moment, but deliver_webhook() later sends requests.post(sub.url, ...) using the original hostname again. Because the resolved IP is not pinned and the destination is not revalidated at delivery time, an attacker can register a hostname that initially resolves to a public IP, pass validation, and then rebind DNS to an internal address before the server sends the webhook.
So the current flow is still bypassable:
- subscribe with
https://attacker.example/webhookwhile it resolves publicly - validation stores the raw URL
- attacker flips DNS to
127.0.0.1,169.254.169.254, RFC1918, etc. deliver_webhook()resolves again implicitly insiderequests.post()and the server-side POST goes to the new internal target
allow_redirects=False helps with redirect-based SSRF, but it doesn't address post-subscription DNS rebinding. To really close the SSRF bug, you need to either re-resolve and re-check on every delivery or pin the validated address and connect to that pinned IP instead of the mutable hostname.
Summary
This change hardens webhook subscriptions against server-side request forgery by validating subscriber destinations before they are stored and by disabling redirect following during delivery.
What changed
Why
The previous implementation accepted attacker-controlled
http://andhttps://subscriber URLs and later issued server-side POST requests to them without checking whether they resolved to internal or reserved addresses. This allowed SSRF into protected network locations.Scope
tools/webhooks/webhook_server.pyonlyCloses #2052
Payout Wallet
RTC1d48d848a5aa5ecf2c5f01aa5fb64837daaf2f35