Credential Stuffing in Adonisjs
How Credential Stuffing Manifests in AdonisJS
Credential stuffing attacks against AdonisJS applications typically exploit two core weaknesses: the absence of rate limiting on authentication endpoints and the lack of multi-factor authentication (MFA). AdonisJS, while providing a robust @adonisjs/auth package, does not enforce rate limiting by default. A typical vulnerable login route in an AdonisJS application might look like this:
// start/routes.ts
Route.post('/login', 'AuthController.login')The corresponding AuthController.login method often validates credentials against the database using Lucid ORM but implements no throttling. An attacker can automate thousands of credential attempts per minute against this endpoint using tools like ffuf or hydra, leveraging credentials from previous data breaches. AdonisJS's session management, if misconfigured (e.g., using weak session stores or missing session regeneration on login), can also allow session fixation, a common adjunct to stuffing attacks. Furthermore, AdonisJS's built-in authentication guards (e.g., 'session' guard) might be applied to protected routes, but the initial authentication entry point remains exposed. The framework's flexibility in defining guards and providers means developers might inadvertently create a login endpoint that accepts any valid user/pair without progressive delays or IP-based blocking, a pattern directly mapped to OWASP API Security Top 10 item A02:2021 – Authentication Broken.
AdonisJS-Specific Detection
Detecting credential stuffing vulnerabilities in an AdonisJS API requires examining the authentication surface for missing controls. First, identify all login endpoints, typically POST /login or POST /auth/login. Check if these routes apply the throttle middleware. AdonisJS provides a @adonisjs/throttle package; its absence is a strong indicator. Second, inspect the auth configuration in config/auth.ts to verify if MFA is enforced for sensitive roles. For automated detection, a scanner must test the login endpoint's response to repeated requests from the same source. middleBrick's scan specifically includes a Rate Limiting check and an Authentication check. When you submit an AdonisJS API URL, middleBrick will:
- Probe the login endpoint with rapid successive requests to detect if HTTP 429 (Too Many Requests) is returned after a threshold.
- Analyze the OpenAPI/Swagger spec (if available) for documented authentication schemes and absence of
429responses on login paths. - Flag missing MFA requirements in the spec's security definitions or in runtime behavior if the endpoint accepts a single factor.
A typical middleBrick finding for this issue would be categorized under Rate Limiting with high severity, stating: "Login endpoint lacks rate limiting, enabling credential stuffing attacks." The report would include the specific endpoint path tested and the raw HTTP responses showing identical 200 OK codes for repeated attempts.
AdonisJS-Specific Remediation
Remediation in AdonisJS leverages the framework's built-in middleware and authentication configuration. The primary fix is to apply the throttle middleware to the login route. Install the throttle package if not present:
npm install @adonisjs/throttleThen, register it in start/kernel.ts:
// start/kernel.ts
import Throttle from '@ioc:Adonis/Addons/Throttle'
Server.middleware.register([
Throttle
])Apply the middleware to the login route with a strict limit. In start/routes.ts:
Route.post('/login', 'AuthController.login')
.middleware('throttle:5,10')
// 5 attempts per 10 minutes for this specific routeFor a global policy on all auth routes, use a route group. Additionally, enforce MFA for privileged users. In config/auth.ts, configure an MFA guard using a provider like Google Authenticator. The AuthController must then check auth.use('mfa').check() after initial password validation for users with mfa_enabled: true in their profile. Finally, ensure session regeneration on successful login to prevent fixation:
// In AuthController.login after verifying credentials
await request.session().regenerate()
await auth.login(user)These steps directly address the detection points: throttle middleware ensures rate limiting returns 429, and MFA enforcement adds a second factor. middleBrick's subsequent scan should then show a passing Rate Limiting check and an improved Authentication score.