HIGH brute force attackstrapibearer tokens

Brute Force Attack in Strapi with Bearer Tokens

Brute Force Attack in Strapi with Bearer Tokens — how this specific combination creates or exposes the vulnerability

A brute force attack against Strapi when Bearer Tokens are used for authentication combines two risk factors: predictable or weak account credentials and unprotected authentication endpoints. Strapi, by default, exposes admin and API routes that can be targeted without requiring a valid session if the API does not enforce strict rate limiting or lockout policies. When Bearer Tokens are used—typically passed via the Authorization header as Authorization: Bearer <token>—the token itself becomes both the secret and the target.

An attacker can perform credential guessing or token enumeration while including a valid or malformed Bearer Token in requests. If Strapi’s admin panel or token validation endpoints do not enforce per-user rate limits, an attacker can iterate through usernames and passwords or attempt token values to discover valid sessions. In some configurations, Strapi may return different HTTP status codes or response bodies for invalid tokens versus invalid credentials, enabling account enumeration. Additionally, if tokens are leaked in logs, browser history, or referrer headers, they can be reused in brute force or token replay attempts. The combination of predictable token generation, missing account lockout, and verbose error messages lowers the effort required to compromise an account.

Consider a scenario where an API endpoint accepts a Bearer Token but does not bind the token to IP or strict scope checks. An attacker can automate requests with slight token mutations or use known token formats to probe for authorization bypass. For example, sending repeated requests with modified Bearer values to an unprotected endpoint can reveal timing differences or error messages that aid an attacker. Inadequate transport security or mixed content can also expose tokens in transit, making interception feasible. Even when tokens are rotated, if the rotation policy is weak or default admin credentials are not changed, brute force and token-guessing attacks remain viable.

Real-world attack patterns include enumeration of admin users via response differences and automated token validation attempts against endpoints that lack proper access controls. Common misconfigurations include allowing unauthenticated access to certain routes or failing to validate the scope of a provided Bearer Token for sensitive operations. These issues map to OWASP API Top 10 controls such as broken authentication and excessive data exposure, and can be referenced against compliance frameworks like PCI-DSS and SOC2.

middleBrick scans for these risks by running parallel checks including Authentication, Rate Limiting, and Input Validation against the unauthenticated attack surface. With 12 security checks running concurrently, it tests how Strapi endpoints respond to malformed or missing Bearer Tokens, looking for inconsistent error handling, missing rate limits, and information leakage. The scan completes in 5–15 seconds and provides prioritized findings with severity ratings and remediation guidance, without requiring credentials or agent installation.

Bearer Tokens-Specific Remediation in Strapi — concrete code fixes

Securing Strapi when using Bearer Tokens requires hardening authentication endpoints, enforcing rate limiting, and ensuring tokens are handled securely. The following examples show how to configure Strapi to mitigate brute force and token-related risks.

First, enforce rate limiting on authentication and token validation routes. In Strapi, you can define custom policies to limit repeated requests. Create a policy file at src/policies/rate-limit.js with the following content:

module.exports = {
  name: 'rate-limit',
  config: {
    points: 5,        // allow 5 requests
    duration: 60,     // per 60 seconds
  },
};

Then apply this policy to your auth routes in src/api/admin/controllers/admin.js or wherever you handle login/token validation:

module.exports = {
  async login(ctx) {
    const { identifier, password } = ctx.request.body;
    // Rate-limited login logic
    const user = await strapi.entityService.findOne('api::user.user', { filter: { identifier } });
    if (!user) {
      ctx.status = 401;
      ctx.body = { error: 'Invalid credentials' };
      return;
    }
    const validPassword = await strapi.plugins['users-permissions'].services.users.validatePassword(password, user.password);
    if (!validPassword) {
      ctx.status = 401;
      ctx.body = { error: 'Invalid credentials' };
      return;
    }
    const token = strapi.plugins['users-permissions'].services.jwt.issue({ id: user.id });
    ctx.body = { token };
  },
};

Second, ensure Bearer Tokens are validated with strict scope and binding checks in protected endpoints. For example, in a custom controller that requires a valid token for sensitive operations:

module.exports = {
  async updateProfile(ctx) {
    const authHeader = ctx.request.header.authorization;
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      ctx.status = 401;
      ctx.body = { error: 'Unauthorized' };
      return;
    }
    const token = authHeader.split(' ')[1];
    try {
      const payload = strapi.plugins['users-permissions'].services.jwt.verify(token);
      // Optionally bind token to user or scope
      if (payload.sub !== ctx.state.user.id) {
        ctx.status = 403;
        ctx.body = { error: 'Forbidden' };
        return;
      }
      // Proceed with update logic
      const updated = await strapi.entityService.update('api::profile.profile', ctx.state.user.profileId, {
        data: ctx.request.body,
      });
      ctx.body = updated;
    } catch (err) {
      ctx.status = 401;
      ctx.body = { error: 'Invalid token' };
    }
  },
};

Third, rotate tokens regularly and avoid exposing token metadata in error messages. Use environment variables for token secrets and ensure HTTPS is enforced site-wide. In Strapi’s config, set strong JWT secrets in config/server.js:

module.exports = ({
  env = process.env.NODE_ENV,
}) => ({
  url: 'https://yourdomain.com',
  host: '0.0.0.0',
  port: 1337,
  admin: {
    auth: {
      secret: process.env.ADMIN_JWT_SECRET,
    },
  },
  jwt: {
    secret: process.env.JWT_SECRET,
  },
});

These steps reduce the effectiveness of brute force attempts by limiting request rates, validating tokens rigorously, and minimizing information disclosure. middleBrick’s checks for Authentication, Rate Limiting, and Input Validation help confirm these controls are effective during scans.

Frequently Asked Questions

How does Strapi respond differently to invalid credentials vs invalid Bearer Tokens?
Strapi should return the same generic error (e.g., 401 Unauthorized with a message like 'Invalid credentials') for both invalid usernames and invalid tokens to avoid account enumeration. Ensure error messages do not reveal whether a username exists and enforce rate limits on all authentication endpoints.
Can middleware help protect Bearer Token usage in Strapi?
Yes. You can create a custom middleware to normalize error responses and enforce token format checks before requests reach controllers. For example, reject requests with malformed Authorization headers early and log anomalies without exposing details to the client.