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.

# Taken from https://ipinfo.io/developers:

# 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

# E.g. $ curl ipinfo.io/8.8.8.8?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:

  1. There had to be a way to make a request to access the widget from the terminal
  2. The widget was heavily rate-limited

Resolving 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

[email protected]:~$ curl https://ipinfo.io/widget/8.8.8.8
Not [email protected]:~$

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”

[email protected]:~$ 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 was allowing 10 requests per user. By that time I had already mentioned that to pry to check this out since he’s been using the API. After around 10 (maybe 15?) seconds he came up with an idea about the rate-limiting problem: using the X-Forwarded-For header.

Acourding 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.

You see, when a server is using 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 each time from a different user/IP. 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

twittercomment

TL;DR: https://twitter.com/vict0ni/status/1417162552266661893

7 Likes