Auth Bypass in Strapi with Basic Auth
Auth Bypass in Strapi with Basic Auth — how this specific combination creates or exposes the vulnerability
Strapi is a headless CMS that supports multiple authentication strategies, including built-in username/password (Basic Auth) via its native users-permissions plugin. When Basic Auth is used without additional constraints, it can expose an unauthenticated attack surface that middleBrick tests as part of its Authentication and BOLA/IDOR checks. An Auth Bypass occurs when an API endpoint that should require valid credentials instead returns data or performs actions without properly validating the Authorization header.
In Strapi, this can happen when a route such as /api/articles/:id is configured to use the users-permissions policy but the policy is either not applied to the route or misconfigured at the controller or service layer. If the endpoint also exposes object-level identifiers in the URL without verifying that the requesting user owns or is permitted to access that object, an authenticated user (or an unauthenticated attacker if the policy is missing) can iterate through numeric IDs and read or modify records that should be restricted. middleBrick’s BOLA/IDOR check specifically tests these scenarios by probing endpoints with different identifiers without valid permissions, looking for missing authorization enforcement.
Another common pattern is relying solely on Basic Auth while exposing administrative or write endpoints without additional safeguards. Basic Auth transmits credentials in an encoded (not encrypted) header unless protected by TLS, and if the API also fails to enforce strict referrer or origin checks, or if CORS is permissive, an attacker may leverage cross-origin requests to make authenticated calls on behalf of a user. middleBrick’s Authentication check verifies whether endpoints that should require credentials reject unauthenticated requests, and its Encryption check ensures that endpoints using Basic Auth are served only over HTTPS.
Real-world exploit patterns mirror findings from known CVEs in CMS products where missing or incorrectly ordered policies allowed unauthorized access to content management endpoints. For example, an endpoint like GET /api/admin/users might return sensitive user lists if the controller omits a policy check or if a role-based condition is miswritten. middleBrick’s Property Authorization check complements this by validating that responses do not overexpose internal fields (such as password hashes or token values) when Basic Auth is in use, which can otherwise lead to privilege escalation or data exposure.
During a scan, middleBrick runs parallel checks across its 12 security controls. For Strapi APIs using Basic Auth, this means validating that authentication is required for admin routes, that object ownership is enforced for user-modifiable resources, and that data exposure does not leak credentials or sensitive fields in responses. The scanner does not modify the server; it reports findings with severity and remediation guidance, enabling teams to tighten policies and controller logic.
Basic Auth-Specific Remediation in Strapi — concrete code fixes
To remediate Auth Bypass risks when using Basic Auth in Strapi, apply explicit policies at the route and controller levels and validate ownership within service logic. The following code examples illustrate secure configurations.
1. Enforce the users-permissions policy on routes
Ensure that routes intended for authenticated users include the policy check. In Strapi, this is typically configured via the policy field in the route’s configuration (e.g., config/policies.js or per-route settings if using custom routers).
// Example policy assignment in a route configuration (Strapi v4) — config/policies.js
module.exports.policies = {
'api::article.article': {
find: ['users-permissions'],
findOne: ['users-permissions'],
create: ['users-permissions'],
update: ['users-permissions'],
delete: ['users-permissions'],
},
'api::admin.admin': {
'*': ['users-permissions', 'admin-only'], // custom admin policy
},
};
2. Validate ownership in controllers/services
Do not rely solely on route-level policies. Within the controller or service, verify that the requesting user is allowed to access the specific resource. For Basic Auth, the user identity is available via the context after authentication.
// Example controller logic (Strapi v4) — src/api/article/controllers/article.js
'use strict';
module.exports = {
async findOne(ctx) {
const { id } = ctx.params;
const user = ctx.state.user; // Authenticated user from Basic Auth
if (!user) {
return ctx.unauthorized('Authentication required');
}
const entry = await strapi.entityService.findOne('api::article.article', id, {
populate: { author: true },
});
// Ensure the user is allowed to view this entry
if (!entry || entry.author.id !== user.id) {
return ctx.unauthorized('You cannot access this resource');
}
return entry;
},
};
3. Use role-based checks for admin endpoints
For administrative operations, combine Basic Auth with role validation to prevent privilege escalation. Do not expose admin endpoints without verifying the user’s role.
// Example admin-only policy — src/policies/admin-only.js
'use strict';
module.exports = async (ctx, next) => {
const user = ctx.state.user;
if (!user || !['super-admin', 'content-manager'].includes(user.role)) {
return ctx.unauthorized('Insufficient permissions');
}
return next();
};
4. Enforce HTTPS for Basic Auth
Because Basic Auth encodes credentials rather than encrypting them, always serve authenticated endpoints over HTTPS. middleBrick’s Encryption check will flag endpoints using Basic Auth without TLS.
// Example enforced in server configuration (e.g., proxy or server.js)
if (process.env.NODE_ENV === 'production' && !ctx.secure) {
ctx.throw(403, 'HTTPS is required for authenticated requests');
}
5. Limit exposure of sensitive fields in responses
Ensure that responses do not include password hashes, reset tokens, or other sensitive fields. Use serialization or response shaping to exclude these fields.
// Example response shaping — src/api/article/services/article.js
async findEntryWithAuth(ctx) {
const entry = await strapi.db.query('api::article.article').findOne({
where: { id: ctx.params.id },
select: ['title', 'content', 'author'], // Exclude password, resetToken, etc.
});
return entry;
}
These measures reduce the risk of Auth Bypass by ensuring that Basic Auth is always enforced, ownership is validated, and sensitive data is protected. middleBrick’s scans can validate these controls by checking Authentication, Encryption, and Property Authorization findings, and teams using the Pro plan can automate this validation through continuous monitoring and CI/CD integration.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |