Bypassing the IPinfo API (feat. pry0cc)
Around October 2020, I was pretty active in the bug hunting community. And of course, I was hunting too, as a form of training and learning process. Around that time, my friend @pry0cc made a utility named ipi
As explained in the README file, this utility was based on the ipinfo.io API. IPinfo is a company providing trusted ASN and IP address data. Its usage is pretty simple: you purchase a subscription and then you use the API, along with the token they provide you when you subscribe.
# With Basic Auth
$ curl -u $TOKEN: ipinfo.io
# With Bearer token
$ curl -H "Authorization: Bearer $TOKEN" ipinfo.io
# With token query parameter
$ curl ipinfo.io?token=$TOKEN
There's also a widget on their website for everyone to test out the API.
This is the part where I thought: if the widget is not secure enough, then that's free IPinfo API, right? Well, after tweaking it, there were two problems with that:
- There had to be a way to make a request to access the widget from the terminal
- The widget was heavily rate-limited
The first issue was quite easy. All I had to do is to see how the request was made to the widget, so I can move it to my terminal.
Apparently, there is a /widget/[IP]
endpoint, where anyone can make a request and get the IP data. Moving this from the browser to the terminal wasn't successful at the beginning
victor@victorLaptop:~$ curl https://ipinfo.io/widget/8.8.8.8
Not Foundvictor@victorLaptop:~$
Of course, since the widget is hosted on their website, it should only listen to requests originating from them. One way to do this is by adding the Referer header. That way, the request "says" to the server, "hey, I'm making this request by using your website, so I'm totally legal."
victor@victorLaptop:~$ curl -H "Referer: https://ipinfo.io/" https://ipinfo.io/widget/8.8.8.8
{
"ip": "8.8.8.8",
"hostname": "dns.google",
"anycast": true,
"city": "Mountain View",
"region": "California",
...
...
Well, there you have it; the first part's done. But the second problem still existed: the rate-limiting mechanism allowed 10 requests per user. By then, I had already mentioned that to pry to check this out since he's been using the API. Pry0cc came up with an idea about the rate-limiting problem: using the X-Forwarded-For
header.
According to developer.mozilla.org
The X-Forwarded-For (XFF) header is a de-facto standard header for identifying the originating IP address of a client connecting to a web server through an HTTP proxy or a load balancer.
When a server uses a reverse proxy or a load balancer, the user's IP address is contained in the X-Forwarded-For
header and passed from the proxy to the main server. If that's the case for IPinfo's server, there might be a chance for the X-Forwarded-For
header value to be overwritten by our value. Changing the header value on every request would look to the server as each request is made from a different user/IP each time. And that worked!
We had a rate limit and enterprise bypass. Once we reported it, it got fixed the same day. And IPinfo's response was awesome.
TL;DR: https://twitter.com/vict0ni/status/1417162552266661893