Security researcher discovers how to send unlimited HTTP requests with the same client
An IP spoofing vulnerability in Django REST allowed attackers to circumvent the framework’s throttling feature, which is supposed to protect applications against mass requests.
Django REST is a popular toolkit for developing web APIs and is used by Mozilla, Red Hat, and Heroku among others. It has a throttling feature that controls the rates of requests a client can make to the API.
This feature is meant to protect applications against bot activity, denial-of-service attacks, and malicious activities such as brute-force attempts on login pages, one-time passwords, and password reset pages.
Spoofing the IP address
Django REST uses IP addresses to identify clients and apply the throttling request limits. However, according to security researcher Hosein Vita, clients can trick the server and mask their IP address by changing their request headers.
“Django use WSGI (web server gateway interface) to communicate with web application and X-Forwarded-For HTTP header and REMOTE_ADDR WSGI variable are used to uniquely identify client IP addresses for throttling,” he told The Daily Swig.
Therefore, if a web request includes the X-Forwarded-For header, the server will consider it to be the client’s IP address. By using different values for the X-Forwarded-For, Vita was able to send unlimited requests with the same client.
According to Vita’s write-up of the bug, the scheme only works for unauthenticated requests. APIs that require user authentication take both the user’s ID and the IP address into account when throttling, so IP spoofing is not enough to circumvent the request limits.
From DDoS to OTP cracking
Vita said that the attack needs no special access to the server and an attacker who “can just see the website can abuse this method.”
Its immediate impact can be DDoS attacks by flooding Django servers with spoofed requests. But it can also serve for other purposes such as circumventing defenses against brute-force attacks on login pages. In fact, Vita discovered the bug while pen testing an application that had a one-time password login page.
“You could log in [to the application] with OTP but I got blocked after many attempts,” he said. “After my research, I used X-Forwarded-For header and again I could send requests but after some attempts, again I got blocked.”
The researcher added: “From my previous background in Django, I guessed it could get bypassed by changing the value of X-Forwarded-For header, and you could send 30 requests with each IP. Then I checked that in my Django API and it was correct.”
The Daily Swig reached out to the Django REST team for comments on the vulnerability. We will update this article if we hear back from them.
In the meantime, Vita has suggested relying on complementary techniques to secure applications against brute-force attacks.
“Always use other aspects of security measures as secondary methods,” he said. “Use Captcha or other related methods to reduce attacks like this in important endpoints. For OTPs, use a token for each generated OTPs.”