HIGH brute force attacksailsbasic auth

Brute Force Attack in Sails with Basic Auth

Brute Force Attack in Sails with Basic Auth — how this specific combination creates or exposes the vulnerability

A brute force attack against a Sails.js application using HTTP Basic Authentication leverages the fact that authentication is performed on each request with no built-in protection against rapid, repeated credential guesses. In this setup, the client sends an Authorization header (e.g., Authorization: Basic base64(username:password)) on every request. If the endpoint does not enforce rate limiting or account lockout, an attacker can systematically submit many username and password combinations and observe HTTP status codes to infer valid accounts.

Because Sails is convention-driven, developers often scaffold API endpoints quickly and may leave authentication to Basic Auth without additional guards. When Basic Auth is used over unencrypted HTTP, credentials are base64-encoded and easily decoded; always use HTTPS to protect credentials in transit. However, even with HTTPS, the lack of rate limiting makes the endpoint vulnerable to online password spraying and credential stuffing. An attacker may target common accounts like admin or service accounts, iterating through passwords or using leaked credential lists.

The application’s session behavior can also amplify risk: if tokens or session cookies are issued after successful Basic Auth and are long-lived, an attacker who cracks a password gains persistent access. Because Basic Auth does not inherently carry mechanisms for one-time tokens or step-up verification, each request simply retransmits the same encoded credentials. In a black-box scan, middleBrick tests authentication endpoints by sending many rapid requests with varying credentials to detect the absence of rate limiting and to surface findings under the Authentication and Rate Limiting checks.

Other contributing factors include predictable or default admin paths (e.g., /admin), missing account lockout after N failures, and permissive CORS rules that allow brute force tooling from the browser. Because Basic Auth transmits credentials in every request, the attack surface remains exposed for as long as the credentials are valid. Credential exposure can lead to unauthorized data access or lateral movement if the same password is reused across services.

middleBrick’s authentication checks under the 12 parallel security scans look for missing rate limiting, lack of account lockout, and excessive response information that aids enumeration. Findings include severity and remediation guidance to help you prioritize fixes and reduce the risk of successful brute force attacks.

Basic Auth-Specific Remediation in Sails — concrete code fixes

To harden Basic Auth in Sails, introduce rate limiting, avoid exposing whether a username exists, and enforce HTTPS. Below are concrete, working examples you can apply in a Sails app.

1. Enforce HTTPS in production

Ensure your Sails app only serves traffic over TLS. In your config/env/production.js, set:

module.exports.enforceHTTPS = true;

2. Add rate limiting using a policy

Create a policy, e.g., api/policies/rate-limit-basic-auth.js, that tracks attempts by IP and delays or rejects excessive requests:

const rateLimit = new Map();

module.exports.ratelimitBasicAuth = async function (req, res, next) {
  const ip = req.ip || (req.headers['x-forwarded-for'] && req.headers['x-forwarded-for'].split(',')[0].trim());
  const now = Date.now();
  const windowMs = 15 * 60 * 1000; // 15 minutes
  const maxAttempts = 5;

  if (!ip) return next();

  const entry = rateLimit.get(ip) || { count: 0, resetAt: now + windowMs };

  if (now > entry.resetAt) {
    entry.count = 0;
    entry.resetAt = now + windowMs;
  }

  entry.count += 1;
  rateLimit.set(ip, entry);

  if (entry.count > maxAttempts) {
    return res.status(429).send({ error: 'Too many attempts. Try again later.' });
  }

  return next();
};

Register this policy in config/policies.js and apply it to your authentication endpoint:

module.exports.policies = {
  'AuthController': {
    'login': ['ratelimitBasicAuth']
  }
};

3. Use a secure login action with constant-time comparison

In your controller, avoid leaking username existence via timing differences. Use a constant-time comparison function and return a generic message:

const crypto = require('crypto');

module.exports.login = async function (req, res) {
  const { username, password } = req.allParams();

  // Fetch user record (example using Waterline)
  const user = await User.findOne({ username });

  // Use a dummy hash to keep timing similar regardless of user existence
  const dummyHash = crypto.randomBytes(64).toString('base64');
  const storedHash = user && user.password ? user.password : dummyHash;

  // Constant-time compare (Node.js built-in timing-safe compare)
  const providedHash = Buffer.from(Buffer.from(password).toString('base64'), 'base64');
  const match = crypto.timingSafeEqual(Buffer.from(storedHash), providedHash);

  if (!match) {
    return res.unauthorized({ error: 'Invalid credentials.' });
  }

  // Issue a session token or set secure, HttpOnly cookie
  return res.ok({ token: 'example-jwt-token' });
};

4. Configure secure cookies and CORS

In config/session.js, ensure cookies are secure and HttpOnly:

module.exports.session = {
  cookie: {
    secure: true,
    httpOnly: true,
    sameSite: 'strict',
    maxAge: 24 * 60 * 60 * 1000
  }
};

Restrict CORS to trusted origins in config/cors.js:

module.exports.cors = {
  origin: 'https://yourapp.example.com',
  credentials: true
};

Frequently Asked Questions

Why does Basic Auth combined with Sails increase brute force risk?
Basic Auth sends credentials with every request and lacks built-in rate limiting. In Sails, if endpoints are not guarded by policies that enforce rate limits or account lockout, attackers can submit many guesses quickly, especially when default routes are used and no HTTPS enforcement or response obfuscation is in place.
How can I test my Sails Basic Auth implementation without a pentest vendor?
You can use the middleBrick CLI to scan your endpoint from the terminal: middlebrick scan https://your-api.example.com/auth/login. It checks for missing rate limiting and authentication weaknesses, providing prioritized findings and remediation guidance without requiring agents or credentials.