My webhook check passed an address that means 127.0.0.1

by•

Our API lets a customer register a URL we call when an invoice is paid. The whole job of that feature is to make a request to an address a stranger chooses, so the check on the address is the security of the feature.

The first version did what most guides say. Allow only http and https, resolve the hostname, and refuse it if PHP filter flags for private and reserved ranges reject the address. Those flags cover the ranges everyone remembers: 10.x, 192.168.x, loopback, and 169.254.169.254, where a cloud server hands out its own credentials to anything that asks from inside.

The first hole was the resolver. The function we called returns IPv4 records only. The HTTP layer resolves the name again and will happily connect over IPv6. So a hostname with a public IPv4 record and a loopback IPv6 record passed the check at registration and again at every send, with no timing trick involved. The fix was asking for both record types and refusing if any single address fails.

The second hole was the flags themselves. Checked one at a time rather than read off a table, six ranges pass them. Four are merely odd, like the shared address space some clouds use for internal networking. Two are translations: a NAT64 address and a 6to4 address can each carry 127.0.0.1 inside an IPv6 address, and a gateway will translate it back. Both passed everything. They now sit in an explicit deny list beside the flags.

What it still does not close, and the code says so in its own comment: we resolve the name, then the transport resolves it again, so a name that answers public now and private a second later slips between the two. We check at registration and again right before every send, and redirects are switched off, which narrows that to one request. Pinning the connection to the address we checked needs an HTTP client we do not have yet.

If you let users give you a URL to call, what does your check look at: the string, the first resolved address, or every one? And has anyone pinned the IP in PHP without leaving the standard stream functions?

5 views

Add a comment

Replies

Be the first to comment