Brute Force Attack in Laravel
How Brute Force Attack Manifests in Laravel
Brute force attacks against Laravel applications primarily target authentication endpoints, such as the default /login route provided by Laravel Breeze, Jetstream, or Fortify. Attackers automate credential stuffing (using known breached username/password pairs) or password spraying (trying common passwords across many accounts) against these endpoints. Laravel's built-in authentication scaffolding does not enforce rate limiting by default on the login route in all installations, especially if developers have customized auth controllers or removed the ThrottleRequests middleware.
A typical attack pattern involves sending rapid, repeated POST requests to /login with varying credentials. For example, an attacker might use a tool like Burp Suite Intruder or a custom Python script to iterate through a wordlist of passwords for a known username. If the application lacks rate limiting, this can lead to:
- Credential stuffing success: Reusing passwords from previous breaches.
- Account lockout evasion: If account lockout is implemented via failed login attempts stored in the session (rather than a centralized, rate-limited store), distributed attacks from multiple IPs can bypass it.
- Denial-of-service: Overwhelming the application with login attempts, consuming resources.
Laravel-specific code paths vulnerable include any route handling authentication that does not apply the throttle:login middleware (or a custom rate limiter). The Illuminate\Foundation\Auth\AuthenticatesUsers trait, used by the default LoginController, does not inherently enforce rate limiting; it relies on middleware attachment. If a developer has overridden the login method or removed the middleware from the route definition, the endpoint becomes exposed.
Additionally, Laravel's session driver for rate limiting (if misconfigured) can be ineffective in distributed environments, as sessions are not shared across servers. Attackers may also target API authentication routes (e.g., /api/login, /oauth/token) if they exist and lack throttling.
Laravel-Specific Detection
Detecting missing or ineffective rate limiting on Laravel authentication endpoints involves testing the unauthenticated attack surface. A scanner should issue repeated login attempts (e.g., 20–30 requests in quick succession) to the login URL and observe responses. Key indicators of vulnerability:
- No
429 Too Many Requestsresponse: After exceeding a reasonable threshold (e.g., 5–10 attempts from the same IP within a minute), the server should return HTTP 429. - No
Retry-Afterheader: A proper rate limit response includes this header indicating the wait time. - Uniform response codes or messages: Even after many attempts, if the response remains
200(success) or401/422(invalid credentials) without change, throttling is absent.
middleBrick's Rate Limiting check specifically tests this. When you submit a Laravel application's login URL (e.g., https://your-app.com/login), middleBrick automatically performs a brute force simulation. It sends a series of authentication requests with intentionally wrong credentials and monitors for rate limiting enforcement. The scanner reports a finding if:
- The endpoint does not return
429after multiple attempts. - The rate limit threshold is too high (e.g., allows 100+ attempts per minute).
- Rate limiting is applied only to authenticated users, not the login endpoint itself.
The finding is categorized under Rate Limiting in the OWASP API Top 10 (API7:2023) and includes a severity rating (typically High for login endpoints). For example, a middleBrick scan might produce a JSON output snippet like:
{
"check": "rate_limiting",
"status": "failed",
"detail": "Login endpoint (/login) did not enforce rate limiting after 20 attempts.",
"severity": "high",
"remediation": "Apply Laravel's throttle middleware to the login route."
}You can integrate this detection into your workflow using the middleBrick CLI: middlebrick scan https://your-app.com/login or via the GitHub Action to catch regressions in CI/CD.
Laravel-Specific Remediation
Laravel provides robust, built-in mechanisms for rate limiting. The primary tool is the ThrottleRequests middleware, which leverages Laravel's RateLimiter facade. Apply this middleware to any route that handles authentication, especially the login and password reset endpoints.
1. Using Middleware on Routes
In your routes/web.php or routes/api.php, attach the throttle middleware to the login route. If using Laravel's default auth scaffolding, the route is typically defined in RouteServiceProvider or via Auth::routes(). You can override or add the middleware:
// routes/web.php
Route::post('/login', [\n App\Http\Controllers\Auth\LoginController::class, 'login'
])->middleware('throttle:5,1'); // 5 attempts per minuteThe throttle:5,1 syntax means 5 attempts per 1 minute. Adjust based on your risk tolerance. For APIs, you might use throttle:api which uses the api rate limiter defined in app/Providers/RouteServiceProvider.php.
2. Custom Rate Limiters in RouteServiceProvider
For more control, define named rate limiters in app/Providers/RouteServiceProvider.php within the configureRateLimiting method:
// app/Providers/RouteServiceProvider.php
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;
public function configureRateLimiting()
{
RateLimiter::for('login', function (Request $request) {
return Limit::perMinute(5)->by($request->ip());
});
// Optional: exponential backoff for repeated failures
RateLimiter::for('login-attempts', function (Request $request) {
return $request->user()
? Limit::perMinute(10)->by($request->user()->id)
: Limit::perMinute(5)->by($request->ip());
});
}Then apply it to your route: ->middleware('throttle:login').
3. Protecting All Auth Routes
If you have multiple auth endpoints (login, register, password/email), group them with the throttle middleware:
Route::middleware(['throttle:auth'])->group(function () {
Route::post('/login', ...);
Route::post('/register', ...);
Route::post('/password/email', ...);
});4. Using Laravel Fortify or Jetstream
If you use Laravel Fortify (which provides the auth backend for Jetstream), rate limiting is often enabled by default for login attempts. Verify in your config/fortify.php that 'limit' is set and 'enable_login_rate_limiting' is true. Fortify uses the login rate limiter key.
5. Session vs. Cache Drivers
Ensure your rate limiting uses a cache driver that works across multiple servers (Redis, Memcached) rather than the file or database drivers if you have a load-balanced setup. Set limiter in config/cache.php or via RateLimiter::useCacheStore('redis').
After implementing these fixes, rescan with middleBrick to confirm the 429 response is triggered after the configured number of attempts. The remediation guidance in middleBrick's report will point you to the specific route lacking throttling, making it easy to verify.
FAQ
Q: Does middleBrick actually attempt logins during the scan?
A: Yes, for the Rate Limiting check, middleBrick sends a series of authentication requests with deliberately invalid credentials to your login endpoint (e.g., /login). It does not use real credentials and only tests for the presence of rate limiting enforcement (HTTP 429 responses). No user accounts are compromised, and the scan is read-only in effect.
Q: My Laravel app uses Laravel Passport for API tokens. Do I need to rate limit the /oauth/token endpoint?
A: Absolutely. The OAuth token endpoint is a prime target for brute force attacks, as it issues access tokens. Apply the same throttle middleware to the route that handles token requests (typically POST /oauth/token). In your routes/api.php or Passport's route registration, add the middleware. middleBrick will detect and report if this endpoint lacks rate limiting.