Auth Bypass in Sails with Basic Auth
Auth Bypass in Sails with Basic Auth — how this specific combination creates or exposes the vulnerability
Sails is a Node.js web framework that does not enforce authentication by default. When Basic Auth is used without additional safeguards, the framework relies entirely on the developer to validate credentials on each route. If route policies or controller logic are incomplete or misconfigured, an unauthenticated attacker may be able to reach endpoints that should be protected.
Basic Auth sends credentials in an Authorization header as base64(username:password). The encoding is not encryption; anyone who can inspect the traffic or intercept the request can easily decode the credentials. In Sails, if routes are exposed without a policy that checks for valid credentials, the base64 string is simply ignored and the request proceeds as if the user is authenticated. This is an example of broken access control (BOLA/IDOR) where the absence of authorization checks leads to an auth bypass.
Common root causes in Sails include missing or incomplete policies, misconfigured CORS allowing unauthorized origins, and controllers that trust request parameters without verifying session or token state. For example, a policy that only checks for the presence of an authorization header, rather than validating the decoded credentials against a user store, provides a false sense of security. Attackers can send requests with arbitrary or missing Authorization headers and, if the policy does not reject them, gain access to sensitive endpoints. The OWASP API Security Top 10 highlights this as a leading risk in API implementations. A runtime scan with middleBrick can surface these gaps by probing endpoints without credentials and identifying responses that should have been protected.
Because Sails applications often expose RESTful routes automatically, an attacker does not need to know the exact endpoint paths. Tools and scanners can iterate over common resource names and detect which routes lack proper authorization. middleBrick’s inventory management and authentication checks are designed to discover such unauthenticated attack surfaces by testing the unauthenticated endpoints and reporting findings mapped to compliance frameworks such as OWASP API Top 10, PCI-DSS, SOC2, HIPAA, and GDPR.
In practice, this vulnerability allows attackers to read, modify, or delete data that should be restricted to specific users or roles. For example, an endpoint like /api/user/profile might return personal information if no valid credentials are verified. The risk severity is high when sensitive data or administrative functions are exposed without proper checks. Remediation requires explicit validation of credentials in policies and robust session or token management, rather than relying on Basic Auth encoding alone.
Basic Auth-Specific Remediation in Sails — concrete code fixes
Remediation centers on enforcing credential validation for every protected route and avoiding reliance on Basic Auth encoding as security. In Sails, use policies to centralize authentication and authorization logic, and ensure controllers only process requests after successful verification.
First, implement a policy that parses and validates the Basic Auth header. The following example shows a policy file api/policies/basicAuth.js that decodes the header and checks credentials against a user model. This policy must be applied to all sensitive routes in config/policies.js.
// api/policies/basicAuth.js
const auth = require('basic-auth');
const bcrypt = require('bcrypt');
module.exports.basicAuth = async function(req, res, next) {
const credentials = auth(req);
if (!credentials || !credentials.name || !credentials.pass) {
return res.unauthorized('Auth credentials required');
}
try {
const user = await User.findOne({ username: credentials.name });
if (!user) {
return res.unauthorized('Invalid credentials');
}
const passwordMatch = await bcrypt.compare(credentials.pass, user.passwordHash);
if (!passwordMatch) {
return res.unauthorized('Invalid credentials');
}
req.user = user;
return next();
} catch (err) {
return res.serverError('Authentication error');
}
};
Second, update config/policies.js to apply this policy to relevant controllers and actions. For instance, protecting all user-related endpoints ensures that no route inadvertently allows access without validation.
// config/policies.js
module.exports.policies = {
UserController: {
'*': 'basicAuth',
'profile': 'basicAuth',
'update': ['basicAuth', 'requireRoleAdmin']
},
AdminController: {
'*': ['basicAuth', 'requireRoleAdmin']
}
};
Third, avoid sending Basic Auth credentials over unencrypted channels. Enforce HTTPS across your Sails application by configuring your proxy or load balancer to terminate TLS and by setting HTTP Strict Transport Security headers. In development, use environment variables to store secrets and avoid hardcoding credentials in policies or models.
Finally, prefer token-based mechanisms for modern applications. If you must use Basic Auth, combine it with short-lived tokens or session cookies after initial validation, and ensure that tokens are scoped with minimal permissions. middleBrick’s authentication and property authorization checks can validate that policies are consistently applied and that endpoints do not allow unauthenticated access, helping you maintain a secure posture as your API evolves.
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 |