Privilege Escalation with Basic Auth
How Privilege Escalation Manifests in Basic Auth
Privilege escalation in Basic Auth APIs occurs when authentication succeeds but authorization fails to properly restrict access to resources. The attacker gains initial access through valid credentials, then exploits authorization flaws to access data or functionality beyond their intended permissions.
Consider a banking API where users authenticate with Basic Auth. An attacker with valid credentials for account 1234 might manipulate request parameters to access account 5678's data. This BFLA (Broken Function Level Authorization) vulnerability allows privilege escalation even though authentication was successful.
// Vulnerable Basic Auth endpoint
app.get('/api/accounts/:accountId', authenticateBasicAuth, (req, res) => {
const accountId = req.params.accountId;
const userId = req.user.id; // from Basic Auth credentials
// BUG: No verification that userId owns accountId
const account = db.getAccount(accountId);
res.json(account);
});The vulnerability lies in the missing authorization check. The server trusts the authenticated user but fails to verify they have permission to access the requested resource.
Another common pattern involves role-based privilege escalation. A Basic Auth system might assign roles (admin, user, guest) but fail to enforce role boundaries:
// Vulnerable role check
app.get('/api/admin/stats', authenticateBasicAuth, (req, res) => {
// BUG: Only checks if authenticated, not if admin
const stats = db.getAdminStats();
res.json(stats);
});Parameter manipulation represents another attack vector. Attackers modify query parameters, headers, or request bodies to escalate privileges:
// Vulnerable to parameter tampering
app.post('/api/transfer', authenticateBasicAuth, (req, res) => {
const { fromAccount, toAccount, amount } = req.body;
// BUG: Trusts client-provided fromAccount without validation
db.transfer(fromAccount, toAccount, amount);
});In this case, an authenticated user could specify any account number as the source, potentially draining other users' accounts.
Horizontal privilege escalation occurs when users access other users' data within the same privilege level. Vertical escalation involves accessing higher-privilege functionality. Both are common in Basic Auth systems where authorization logic is weak or missing.
Basic Auth-Specific Detection
Detecting privilege escalation in Basic Auth requires examining both authentication flows and authorization logic. The first step is verifying that Basic Auth credentials map to specific user identities that are tracked throughout the request lifecycle.
Manual testing involves attempting to access resources across user boundaries. After authenticating as one user, try accessing other users' data by manipulating resource identifiers in URLs, request bodies, or headers. Look for patterns like:
GET /api/users/123/profile HTTP/1.1
Authorization: Basic dXNlcjpwYXNzd29yZA==
Then modify the user ID to access other profiles. If the server returns data without additional authorization checks, you've found a privilege escalation vulnerability.
Automated scanning tools like middleBrick can detect these issues by testing unauthenticated endpoints for authorization bypasses. The scanner attempts to access protected resources without proper authentication tokens, then analyzes responses for data leakage or functionality access.
middleBrick's privilege escalation detection specifically tests Basic Auth endpoints by:
- Attempting to access admin endpoints with regular user credentials
- Manipulating resource identifiers in authenticated requests
- Testing for missing authorization headers or token validation
- Checking for role-based access control bypasses
- Scanning for excessive data exposure in error messages
The scanner's 12 parallel security checks include BFLA/Privilege Escalation testing that examines how Basic Auth credentials are validated against requested resources. It looks for patterns where authentication succeeds but authorization fails to restrict access appropriately.
Key indicators of privilege escalation vulnerabilities include:
- HTTP 200 responses to unauthorized resource requests
- Partial data exposure showing other users' information
- Successful admin function calls with regular user credentials
- Missing or ineffective role-based access controls
Basic Auth-Specific Remediation
Remediating privilege escalation in Basic Auth requires implementing proper authorization checks throughout your API. The foundation is verifying that authenticated users can only access resources they own or have explicit permission to view.
Start with a robust authorization middleware that validates resource ownership:
// Authorization middleware for Basic Auth
function authorizeResource(req, res, next) {
const userId = req.user.id; // from Basic Auth credentials
const resourceId = req.params.resourceId || req.body.resourceId;
// Verify user owns or has permission to access resource
db.checkResourcePermission(userId, resourceId)
.then(hasPermission => {
if (!hasPermission) {
return res.status(403).json({
error: 'Forbidden: Insufficient permissions'
});
}
next();
})
.catch(next);
}Apply this middleware to all resource-accessing endpoints:
app.get('/api/accounts/:accountId', authenticateBasicAuth, authorizeResource, (req, res) => {
const accountId = req.params.accountId;
const account = db.getAccount(accountId);
res.json(account);
});For role-based systems, implement comprehensive role checking:
function requireRole(requiredRole) {
return function(req, res, next) {
const userRole = req.user.role; // from Basic Auth credentials
if (userRole !== requiredRole) {
return res.status(403).json({
error: `Forbidden: ${requiredRole} role required`
});
}
next();
};
}Apply role requirements to sensitive endpoints:
app.get('/api/admin/stats', authenticateBasicAuth, requireRole('admin'), (req, res) => {
const stats = db.getAdminStats();
res.json(stats);
});Implement principle of least privilege by validating all user-supplied parameters against the authenticated user's context:
app.post('/api/transfer', authenticateBasicAuth, (req, res) => {
const { fromAccount, toAccount, amount } = req.body;
const userId = req.user.id;
// Validate that fromAccount belongs to authenticated user
db.getAccountOwner(fromAccount)
.then(ownerId => {
if (ownerId !== userId) {
return res.status(403).json({
error: 'Cannot transfer from account you don''t own'
});
}
// Proceed with transfer
return db.transfer(fromAccount, toAccount, amount);
})
.then(() => res.json({ success: true }))
.catch(next);
});Always use secure comparisons for authorization checks to prevent timing attacks:
function secureCompare(a, b) {
if (a.length !== b.length) return false;
let result = 0;
for (let i = 0; i < a.length; i++) {
result |= a.charCodeAt(i) ^ b.charCodeAt(i);
}
return result === 0;
}Log authorization failures for security monitoring and implement rate limiting on authorization endpoints to prevent brute force attacks on permission boundaries.