Elixir/Phoenix Security: How attackers bypass IP based rate limiting

Michael Lubas, 2022-12-20

“Limit the number of login attempts for one IP address to 5 in a 30 second period” is a standard rule for many web applications, and makes sense from the perspective of a site owner dealing with malicious credential stuffing. With the rise of cloud computing, it has become much easier for an attacker to access thousands of different IP addresses, for free, to bypass IP based blocking. This article will use a Phoenix application to demonstrate what the attack looks like, and how Paraxial.io stops it.

AWS API Gateway

AWS API Gateway is a service that handling incoming traffic for a web application, such as HTTP requests, and then triggers some application functionality. The important point for attackers is that the gateway can be pointed at a victim web application, so that when the attacker sends traffic to the gateway, it is proxied through an AWS server, changing the IP address. David Yesland from Rhino Security describes this technique in a blog post, and introduces a Burp Suite extension which can be used to proxy traffic through AWS.

blackcatprojects.xyz is a simple Phoenix application, which will be the target of this traffic. Using Burp Suite, we proxy our traffic through API Gateway, then check the backend logs of blackcatprojects.xyz to see the requests:

Each HTTP request has a different IP from AWS, exactly what an attacker needs to bypass the rule, “Limit the number of login attempts for one IP address to 5 in a 30 second period”.

Cloud IPs and Plug

Amazon publishes the IP ranges of AWS, so it is possible to determine if an incoming request originates from AWS. In most cases, traffic from a cloud provider’s IP range is coming from a bot, however not all bots are malicious. For example, tools to monitor your site’s uptime often rely on cloud hosted bots sending HTTP requests. Blocking bot traffic to the site’s main page is not desirable, but it’s exactly what you want on the login page.

The best way to achieve this in Phoenix is with a Plug, one that looks at an incoming conn’s remote_ip, determines if it matches a known list of cloud IPs, and then allows or halts the request. The implementation of such a Plug is covered in the post Classifying Data Center IP Addresses in Phoenix Web Applications with Radix Trees.

There are a few problems with the system described:

1. Your startup time will increase due to the outbound HTTP requests, parsing JSON, and creating the radix trie.

2. If your business has an important customer whose VPN is hosted on a cloud provider, you now need to implement an allow list.

3. The increased memory usage may cause deployments on instances with a low amount of memory (256mb) to fail, due to the HTTP requests getting lists of IPs from each cloud provider.

Paraxial.io’s Elixir agent is able to retrieve a radix trie at startup, for use with the Paraxial.BlockCloudIP Plug. This plug can block the attack described above, with the added benefit of a web interface to add IPs to an allow list.

In the blackcatprojects.xyz router:

  pipeline :block_cloud_requests do
    plug Paraxial.BlockCloudIP

  ## Authentication routes

  scope "/", HavanaWeb do
    pipe_through [:browser, :redirect_if_user_is_authenticated, :block_cloud_requests]

    get "/users/register", UserRegistrationController, :new
    post "/users/register", UserRegistrationController, :create
    get "/users/log_in", UserSessionController, :new
    post "/users/log_in", UserSessionController, :create
    get "/users/reset_password", UserResetPasswordController, :new
    post "/users/reset_password", UserResetPasswordController, :create
    get "/users/reset_password/:token", UserResetPasswordController, :edit
    put "/users/reset_password/:token", UserResetPasswordController, :update

The attack is blocked against the /users/log_in route, and good bots can continue to access the main page of the site.

IP based rate limiting is an important tool for defenders, and should be implemented as a first line of defense against attackers. The technique described in this article with API Gateway is well known to attackers, low cost, and often bypasses throttling rules. Sensitive endpoints in your application, such as the login form, 2FA code submission, and new user registration should reject attempts coming from a rented cloud server.

Paraxial.io stops data breaches by securing your Elixir and Phoenix apps. Detect and fix critical security issues today.

Subscribe to stay up to date on new posts.