Webhook SSRF Bug Bounty: Hunting Outbound URL Callbacks
Webhooks are SSRF with a product manager’s blessing. The app promises “we’ll POST to your URL when an event fires.” That worker often sits deep in the VPC with broader egress than the public web tier.
I treat every “callback URL,” “notify URL,” “avatar from URL,” and “import feed” field as a fetch sink until proven otherwise.
Finding the sink
Search settings for Integrations, Slack/Discord hooks, payment IPNs, CI status targets, Zapier-style automation, and “test webhook” buttons. Mobile and partner APIs sometimes expose webhook_url without a UI.
Trigger path matters. A URL that is only stored but never fetched is weak. A “Send test event” button is gold — instant SSRF without waiting for a real order.
Prove outbound first
Point the webhook at your Burp Collaborator / interactsh / a VPS you own. Confirm DNS + HTTP from the vendor’s IP ranges. Screenshot the hit. That alone is often not a vuln (expected behavior), but it establishes the sink for the rest of the report.
Then aim inward
Programs care when you reach:
- Cloud metadata (see IMDSv2 constraints)
- Internal admin panels (
http://127.0.0.1,http://localhost, RFC1918) - Kubernetes/metadata-ish endpoints on cloud providers
- Sibling services by internal hostname guessed from JS or error text
Try redirects: webhook follows 302 to internal. Try DNS rebinding only if policy allows and you understand the risk. Prefer clear, low-noise proofs.
Weird constraints hunters hit
- HTTPS-only allowlists (still try atypical ports, userinfo, or open redirect on an allowed host)
- HEAD vs POST differences
- Response body returned to the UI (“webhook debugger” that reflects headers — turns SSRF into info leak)
- IP denylists that miss IPv6 or decimal forms
Report shape that works
- Feature name and role needed to set the URL.
- Collaborator proof of egress.
- Internal target hit (status/body snippet redacted).
- Impact: network position of the worker, not just “SSRF exists.”
- Fix: allowlist schemes/hosts, block link-local and private ranges, disable redirects, authenticate egress.
Defensive one-liner for teams
If your product fetches customer URLs, assume the customer is adversarial. Fetch from a locked-down proxy with an allowlist — never from the application subnet with default routes.
Webhook SSRF is ordinary product functionality pointed at extraordinary network access. Test the test button first; then see where the worker can walk.