..

Bypassing the IPinfo API (feat. pry0cc)

Around October 2020, I was pretty active on 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

ipi README

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

widget

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

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.

request

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 successfull 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, 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 ovewritten 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!

BRUH

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