The Target
A SaaS product management platform that lets teams manage features, feedback, and roadmaps. The platform supports webhook notifications and plugin integrations where users provide a URL, and the server makes outbound HTTP requests to it when events fire.
The Discovery
I started by testing what URLs the webhook creation endpoint would accept. Standard private IPs like 127.0.0.1 and 10.0.0.1 were correctly blocked with an "Invalid host" error. But when I tried the AWS cloud metadata IP 169.254.169.254, the webhook was created successfully with a 201 response. The IPv4-mapped IPv6 version [::ffff:169.254.169.254] was also accepted.
The blocklist existed but had gaps. It covered the obvious private ranges but missed the entire 169.254.0.0/16 link-local range.
The Escalation
Cloud metadata bypass: Created a webhook pointing to https://169.254.169.254/latest/meta-data/iam/security-credentials/. The server accepted it (201 Created). Also worked with the IPv6-mapped variant. The connection failed at the network level because metadata wasn't accessible in their current infrastructure, but the URL passed all validation.
Plugin probe confirms server-side requests: The plugin integration endpoint makes a synchronous GET request during creation and returns detailed error messages. Pointing it at the platform's own health endpoint returned "Validation token does not match," confirming the server connected, got a 200, and read the response body. This also worked against staging/admin subdomains, leaking that they returned 200.
DNS rebinding, full blocklist bypass: The URL validation resolved DNS before the blocklist check but did not re-validate on the actual connection. Using a DNS rebinding domain (first resolves to a public IP, then rebinds to the target internal IP), I bypassed every blocked IP. 127.0.0.1, 10.0.0.1, 169.254.169.254, all accepted with 201 Created. The plugin probe confirmed connection attempts were made to the rebound addresses.
Impact
- Internal service mapping via error-based HTTP status code leaks from the plugin probe
- Full IP blocklist bypass via DNS rebinding, including 127.0.0.1 and 10.0.0.1
- Cloud metadata range (169.254.0.0/16) not blocked, risk of credential theft if infrastructure changes
- Staging and admin subdomains reachable and confirmed responding with 200
Timeline
Reported and triaged within a day. Initially rated Medium because the cloud metadata IP wasn't reachable in their current setup. After submitting the DNS rebinding bypass showing the entire blocklist was ineffective, severity was upgraded to High with an increased bounty.
Takeaway
IP blocklists for SSRF are almost always incomplete. If you find a webhook or callback feature, don't stop at the obvious private ranges. Test cloud metadata IPs, IPv4-mapped IPv6, and DNS rebinding. The rebinding technique is especially effective because most implementations validate DNS at creation time but don't re-check when the actual request is made. Also pay attention to error messages. In this case, the plugin probe leaked HTTP status codes from internal services, turning a blind SSRF into an error-based internal scanner.