HIGH password sprayingfeathersjs

Password Spraying in Feathersjs

How Password Spraying Manifests in FeathersJS

Password spraying is a brute-force attack that attempts a few common passwords (e.g., Password123, admin) against many user accounts to avoid account lockouts. In FeathersJS applications, this vulnerability typically manifests in the authentication service, which by default exposes a /auth/login endpoint (or a custom service) that accepts credentials via JSON or form data. FeathersJS's stateless JWT authentication, while convenient, often lacks built-in brute-force protection, making the login endpoint a prime target.

FeathersJS services are built on Express middleware, and the authentication flow usually involves a custom AuthenticationService or a hook that calls feathers.authenticate('jwt') or similar strategies. An attacker can script repeated POST requests to this endpoint with different usernames and a common password. Because FeathersJS does not impose rate limits by default, and many deployments skip adding them, the application may respond with distinct error messages for invalid credentials versus user not found, inadvertently confirming valid usernames (user enumeration).

For example, a vulnerable FeathersJS auth service might look like this:

// services/authentication/authentication.class.js
const { AuthenticationService } = require('@feathersjs/authentication');
const { JWTStrategy } = require('@feathersjs/authentication-jwt');

module.exports = class AuthenticationService extends AuthenticationService {
  setup(app) {
    super.setup(app);
    this.register('jwt', new JWTStrategy());
    // No rate limiting or login attempt tracking
  }
};

// services/users/users.class.js (no hook to track failures)
module.exports = class UsersService extends Service {
  async find(params) { return this._super.find(params); }
};

// No middleware applied globally to /auth/login

Attackers can use tools like ffuf or custom scripts to spray passwords against the /auth/login endpoint, exploiting the absence of throttling and potentially harvesting valid usernames from response differences.

FeathersJS-Specific Detection

Detecting password spraying vulnerabilities in a FeathersJS API involves examining both the authentication service's behavior and the presence of rate-limiting mechanisms. middleBrick's scan includes targeted checks for Rate Limiting and Authentication flaws, which directly apply to FeathersJS applications. The scanner sends sequential login attempts with common passwords and varied usernames to identify:

  • No rate limiting: Whether the /auth/login (or equivalent) endpoint allows rapid, repeated requests without HTTP 429 responses.
  • User enumeration: Whether error messages differ between Invalid credentials (valid username, wrong password) and User not found.
  • Lack of multi-factor or captcha: Whether additional verification steps are missing after repeated failures.

FeathersJS apps often use Express middleware, so detection also checks for common rate-limiting packages like express-rate-limit or rate-limiter-flexible in the startup code. For example, if the app's src/app.js or src/middleware/ does not include a rate limiter applied to /auth/login, middleBrick will flag this as a high-risk finding.

You can scan your FeathersJS API with middleBrick's CLI to get a detailed report:

middlebrick scan https://your-feathers-api.com/auth/login

The scan returns a risk score (A–F) with per-category breakdowns. A low score in the Rate Limiting category indicates susceptibility to password spraying. The report also includes prioritized findings with remediation guidance specific to your API's structure.

Additionally, middleBrick's OpenAPI/Swagger analysis (if you provide a spec) cross-references the /auth/login path definition with runtime behavior, checking if rate limits are documented or implemented.

FeathersJS-Specific Remediation

Remediating password spraying in FeathersJS requires implementing robust rate limiting and consistent error responses. FeathersJS's hook system and Express middleware integration make this straightforward. Below are concrete, FeathersJS-specific fixes.

1. Apply Rate Limiting to the Authentication Endpoint

Use the express-rate-limit package in your FeathersJS middleware. Configure it to limit login attempts by IP and/or username. Create a custom middleware and apply it only to the /auth/login route.

// src/middleware/rate-limit-login.js
const rateLimit = require('express-rate-limit');

const loginRateLimit = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5, // Limit each IP to 5 login requests per windowMs
  message: 'Too many login attempts, please try again later.',
  standardHeaders: true,
  legacyHeaders: false,
});

module.exports = loginRateLimit;

Then, in your FeathersJS app configuration (src/app.js), register this middleware specifically for the authentication service:

// src/app.js
const loginRateLimit = require('./middleware/rate-limit-login');

module.exports = function (app) {
  // ... other setup
  // Apply rate limiting only to the authentication service's login method
  app.service('authentication').hooks({
    before: {
      create: [loginRateLimit] // Applies to POST /authentication
    }
  });
  // Alternatively, use Express middleware directly if using a custom route
  // app.use('/auth/login', loginRateLimit);
};

2. Prevent User Enumeration

Ensure the authentication service returns a generic error message for both invalid usernames and passwords. Override the default behavior in your AuthenticationService or use a hook to catch NotFound errors and re-throw a generic message.

// services/authentication/authentication.hooks.js
const { AuthenticationService } = require('@feathersjs/authentication');

module.exports = {
  before: {
    create: [
      async context => {
        const { data } = context;
        // Your custom logic if needed
        return context;
      }
    ]
  },
  error: {
    create: [
      async context => {
        if (context.error.code === 404) {
          // Feathers throws 404 for user not found; convert to generic 401
          context.error = new Error('Invalid credentials');
          context.error.code = 401;
        }
        return context;
      }
    ]
  }
};

// Then register these hooks in your service class or app.js

3. Implement Progressive Delays and Account Lockout

For stronger protection, track failed login attempts per username/IP and introduce delays or temporary lockouts. Use a database or cache (e.g., Redis) to store counters. FeathersJS hooks can update these counters before/after authentication attempts.

// services/authentication/hooks/track-login-attempts.js
const redis = require('redis');
const client = redis.createClient({ url: process.env.REDIS_URL });

module.exports = async context => {
  const { data } = context;
  const key = `login_attempts:${data.email || data.username}`;
  const attempts = await client.get(key);
  if (attempts && parseInt(attempts) >= 5) {
    throw new Error('Account temporarily locked due to too many failed attempts');
  }
  return context;
};

// In error hook, increment the counter on failure
module.exports = {
  error: {
    create: [
      async context => {
        if (context.error.code === 401) {
          const { data } = context;
          const key = `login_attempts:${data.email || data.username}`;
          await client.incr(key);
          await client.expire(key, 900); // 15 minutes
        }
        return context;
      }
    ]
  }
};

These changes directly address password spraying by limiting request rates, eliminating username confirmation, and adding lockout mechanisms—all within FeathersJS's native patterns.

Frequently Asked Questions

Does FeathersJS include built-in protection against password spraying?
No. FeathersJS provides the authentication service and strategies (like JWT) but does not include built-in rate limiting or brute-force protection for the login endpoint. Developers must implement these controls manually using Express middleware or custom hooks, as shown in the remediation section.
How can I integrate middleBrick into my FeathersJS CI/CD pipeline?
Use the middleBrick GitHub Action to scan your FeathersJS API on every push or pull request. In your workflow file, add a step that runs middlebrick/scan-action@v1 with your API's URL. You can configure the action to fail the build if the security score drops below a threshold (e.g., 'B'), ensuring new code doesn't introduce authentication flaws like missing rate limits.