/icons/proxy.png
/icons/rate-limiting.png

Bypassing Rate Limiting Using the X-Forwarded-For Header: A Deep Dive

@red_sh4d0w / June 23, 2024
4 min read

Bypassing Rate Limiting Using the X-Forwarded-For Header: A Deep Dive

In today’s internet landscape, protecting web applications from brute-force attacks is crucial. One of the key defenses against such attacks is rate limiting, which restricts the number of requests a client can make within a certain period. However, attackers often find clever ways to circumvent these protections. A notable method involves exploiting the X-Forwarded-For (XFF) header to bypass rate limiting.

In this blog post, we'll explore how attackers can manipulate the X-Forwarded-For header to evade rate limiting, the underlying reasons why this happens, and the strategies to mitigate this vulnerability.

What is Rate Limiting and Why is it Important?

Rate limiting is a security mechanism used to control the frequency of requests a client can make to a server. It serves several important functions:

  • Preventing Abuse: By limiting the number of requests per unit of time, rate limiting helps protect servers from being overwhelmed by excessive traffic, often seen in denial-of-service (DoS) attacks.
  • Ensuring Fair Usage: It ensures equitable access to resources, preventing any single user from monopolizing the service.
  • Protecting Backend Systems: Rate limiting guards backend systems and APIs against excessive load, helping to maintain system stability and performance.

Rate limiting is commonly based on the client’s IP address. If a client exceeds the predefined request limit, subsequent requests from the same IP are blocked or delayed, thus mitigating potential abuse.

The Role of the X-Forwarded-For Header

The X-Forwarded-For header is a standard HTTP header used to identify the originating IP address of a client connecting to a web server through a proxy or load balancer. For example:

X-Forwarded-For: 198.51.100.1

When multiple proxies are involved, each one adds its IP address to the list in the header. The structure then looks like this:

X-Forwarded-For: 198.51.100.1, 203.0.113.2, 198.51.100.3

In this sequence, 198.51.100.1 is the client’s original IP address, and the following addresses are those of the proxies the request has passed through.

How Attackers Exploit X-Forwarded-For to Bypass Rate Limiting

Why It Happens: The X-Forwarded-For header can be manipulated because it is client-controlled and was originally designed for logging and analytics, not security. Many servers and applications accept this header without strict validation, assuming its contents are accurate and trustworthy. Attackers leverage this trust to inject fake IP addresses, bypassing the rate limiting that relies on the true client IP.

Here’s a breakdown of how attackers exploit this vulnerability:

  • Crafting Requests with Different IPs: Attackers can modify the X-Forwarded-For header in each request to include a different IP address. This makes it appear as though each request is coming from a different client.

    Example:

    X-Forwarded-For: 203.0.113.10
    X-Forwarded-For: 203.0.113.11
    X-Forwarded-For: 203.0.113.12
    
  • Evading Detection: By changing the X-Forwarded-For header, attackers can make hundreds or thousands of requests without being blocked, as the server’s rate limiting mechanism treats each request as coming from a new IP.

  • Automated Attacks: Using automated tools, attackers can rapidly iterate through IP addresses in the X-Forwarded-For header, allowing them to bypass rate limits and perform brute-force attacks or overwhelm the server.

Real-World Scenario: Proof of Concept (PoC)

To illustrate this attack, consider an application that locks an account after three failed login attempts from the same IP address. An attacker can bypass this protection by changing the X-Forwarded-For header in each request, simulating different IP addresses.

Sample HTTP Requests:

POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
X-Forwarded-For: 192.0.2.1

username=admin&password=wrongpassword1
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
X-Forwarded-For: 192.0.2.2

username=admin&password=wrongpassword2

Despite the repeated failed login attempts, the server’s rate limiting and account lock mechanisms are bypassed because each request appears to originate from a different IP address.

Why Does This Vulnerability Exist?

  • Lack of IP Validation: Many servers and applications do not validate the X-Forwarded-For header rigorously. They accept the header as is, without checking whether the IPs listed are valid or should be trusted.

  • Misconfiguration: Web applications and servers might be improperly configured to accept X-Forwarded-For headers from any source, including untrusted or external clients.

  • Assumption of Trust: The header was originally intended to provide information rather than for security enforcement. Systems that rely on this header for rate limiting may inadvertently trust its contents, making them vulnerable to manipulation.

  • Complex Proxy Chains: In environments with multiple proxies, accurately determining the original client IP can be challenging. Attackers exploit this complexity to inject fake IPs into the X-Forwarded-For header.


References:

  • OWASP: Rate Limiting
  • Nginx: Understanding X-Forwarded-For
  • Cloudflare: What is X-Forwarded-For?

GithubLinkedInTwitter