Credential Stuffing in Feathersjs (Javascript)
Credential Stuffing in Feathersjs with Javascript
Feathersjs is a lightweight framework for building real-time APIs and web applications, often used with Node.js and Express under the hood. Its service-based architecture encourages rapid development, but when authentication is implemented without proper rate limiting or credential validation, it becomes vulnerable to credential stuffing attacks. Credential stuffing occurs when attackers use automated tools to test large volumes of username-password pairs (often from breached databases) against login endpoints, exploiting the fact that users reuse credentials across services.
In a typical Feathersjs application, authentication is handled via plugins like @feathersjs/authentication and @feathersjs/authentication-local. If these are configured without request throttling or account lockout mechanisms, an attacker can send hundreds of login attempts per second to the /auth/local endpoint. Since Feathersjs does not enforce rate limits by default, each request proceeds to validate credentials against the user database, consuming resources and potentially leading to account takeover.
This risk is amplified in Feathersjs because services are often exposed via REST, WebSocket, or HTTP endpoints with minimal boilerplate. For example, a Feathersjs service generated with the CLI (feathers generate service) creates routes that are immediately accessible. If authentication is added later without protective middleware, the attack surface remains high. Real-world incidents like the 2019 MongoDB breach (where attackers used credential stuffing to access databases) highlight how such attacks can lead to data exfiltration when combined with weak API protections.
middleBrick detects this vulnerability by scanning the unauthenticated attack surface. It tests login endpoints for rate limiting, checks for account enumeration via response timing or error messages, and validates whether failed attempts trigger delays or CAPTCHAs. Without these controls, the scanner flags the endpoint as high risk under the 'Authentication' and 'Rate Limiting' categories, providing remediation guidance based on OWASP API Security Top 10 (API2:2023 - Broken Authentication).
Javascript-Specific Remediation in Feathersjs
To mitigate credential stuffing in a Feathersjs application, implement rate limiting and secure authentication practices using JavaScript. Feathersjs middleware can be added to protect the authentication route. The following example shows how to add rate limiting to the local authentication endpoint using express-rate-limit, a widely adopted package.
// src/middleware/rateLimit.js
const rateLimit = require('express-rate-limit');
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // limit each IP to 5 login requests per window
message: {
error: 'Too many login attempts from this IP, please try again after 15 minutes'
},
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
});
module.exports = authLimiter;
Apply this middleware to the authentication route in your Feathersjs application. In src/app.js or where services are configured:
const authLimiter = require('./middleware/rateLimit');
app.configure(authentication);
app.use('/auth/local', authLimiter, app.service('authentication').getHooks());
// Note: Adjust path based on your auth service setup
Additionally, prevent account enumeration by ensuring login responses are identical whether the user exists or not. Modify the local authentication strategy to return a generic error:
// src/services/authentication/authentication.js
const { AuthenticationService, JWTStrategy } = require('@feathersjs/authentication');
const { LocalStrategy } = require('@feathersjs/authentication-local');
class SecureLocalStrategy extends LocalStrategy {
async authenticate(params) {
try {
return await super.authenticate(params);
} catch (error) {
// Always return the same error to avoid leaking user existence
throw new Error('Invalid email or password');
}
}
}
module.exports = function (app) {
const authentication = new AuthenticationService(app);
authentication.register('jwt', new JWTStrategy());
authentication.register('local', new SecureLocalStrategy());
app.use('/authentication', authentication);
};
Finally, enable password hashing with bcrypt (already default in Feathersjs) and consider adding multi-factor authentication via plugins like @feathersjs/authentication-oauth2. These JavaScript-specific controls directly address the credential stuffing vector by limiting request velocity and obscuring authentication feedback, reducing risk without requiring agents or configuration changes—aligning with middleBrick’s agentless scanning philosophy.