fix: prevent login rate limit bypass via spoofed headers

The login and forgot-password rate limiters were vulnerable to bypass
by manipulating the X-Forwarded-For header. Attackers could rotate
this header value to circumvent the 5 attempts per minute limit.

Changed both rate limiters to use server('REMOTE_ADDR') instead of
ip() to prevent header spoofing. REMOTE_ADDR gives the actual
connecting IP before proxy headers are processed.

Also added comprehensive unit tests to verify the fix.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Andras BacsaiandClaude committed 2025-10-28 09:47:13 +01:00
1 parent cc070f2ee6
commit f300ba0118
2 files changed
+175 -2

No files matched your search

+8 -2
View File
@@ -127,13 +127,19 @@ class FortifyServiceProvider extends ServiceProvider
});
RateLimiter::for('forgot-password', function (Request $request) {
return Limit::perMinute(5)->by($request->ip());
// Use real client IP (not spoofable forwarded headers)
$realIp = $request->server('REMOTE_ADDR') ?? $request->ip();
return Limit::perMinute(5)->by($realIp);
});
RateLimiter::for('login', function (Request $request) {
$email = (string) $request->email;
// Use email + real client IP (not spoofable forwarded headers)
// server('REMOTE_ADDR') gives the actual connecting IP before proxy headers
$realIp = $request->server('REMOTE_ADDR') ?? $request->ip();
return Limit::perMinute(5)->by($email.$request->ip());
return Limit::perMinute(5)->by($email.$realIp);
});
RateLimiter::for('two-factor', function (Request $request) {