CWE-384 in APIs
- CWE ID
- CWE-384
- Category
- Authentication
- Severity
- HIGH
- Short Name
- Session Fixation
What is Cwe 384?
Cwe 384 (Missing Authorization) is a critical API security weakness where an application fails to properly verify that a user has the necessary permissions to perform an action or access a resource. This allows attackers to bypass authorization controls and perform operations they shouldn't be allowed to execute.
The weakness manifests when applications assume that authentication alone is sufficient for security. After verifying who a user is (authentication), the system must also verify what that user is allowed to do (authorization). Cwe 384 occurs when this second critical step is skipped, implemented incorrectly, or can be bypassed.
Common scenarios include:
- API endpoints that don't validate user permissions before processing requests
- Direct object references without ownership verification
- Missing or ineffective access control checks in middleware
- Authorization logic that can be manipulated through request parameters
This weakness is particularly dangerous because it often provides attackers with complete system access once discovered, potentially leading to data breaches, privilege escalation, and complete system compromise.
Cwe 384 in API Contexts
In API environments, Cwe 384 takes on specific forms that are unique to the stateless, request-response nature of web services. APIs often handle multiple tenants, roles, and resource types, making proper authorization more complex than in traditional web applications.
Common API manifestations include:
- Resource-based authorization failures: An API endpoint like
GET /users/{id}/profilereturns user data without verifying that the authenticated user owns that profile or has permission to view it. - Action-based authorization gaps: A
POST /admin/usersendpoint allows any authenticated user to create administrative accounts because it lacks role-based access control. - Cross-tenant data exposure: Multi-tenant APIs fail to isolate data between customers, allowing one tenant to access another's resources through ID manipulation.
- Missing method-level authorization: Different HTTP methods (GET, POST, DELETE) on the same endpoint have inconsistent permission checks.
APIs are particularly vulnerable to Cwe 384 because they're designed for programmatic access, making them easier to probe systematically. Attackers can quickly enumerate endpoints and test authorization bypasses using automated tools, often without triggering traditional security alerts.
Detection
Detecting Cwe 384 requires both manual code review and automated testing approaches. Here's how to identify this weakness:
Manual Code Review:
- Search for authorization checks in your codebase using patterns like
if (user.hasPermission()),authorize(), or role-based access control logic - Identify all API endpoints and verify that each has appropriate authorization checks
- Look for direct database queries that use user-provided IDs without ownership verification
- Check for missing authorization in error handling paths and edge cases
Automated Testing:
- Create test accounts with different permission levels and attempt to access restricted resources
- Modify request parameters (IDs, user tokens) to access other users' data
- Test endpoint access with different authentication states (logged in vs. not logged in)
- Verify that changing user roles in requests affects access control as expected
Using middleBrick for Detection:
middleBrick automatically scans for Cwe 384 through its BOLA/IDOR (Broken Object Level Authorization / Insecure Direct Object References) and Property Authorization checks. The scanner tests whether authenticated endpoints properly enforce authorization by attempting to access resources across different user contexts.
For example, middleBrick will:
- Attempt to access user-specific resources using different authentication tokens
- Test whether resource IDs can be manipulated to access unauthorized data
- Verify that administrative endpoints are properly protected
- Check for missing authorization in CRUD operations
The scanner provides a security score with specific findings for authorization weaknesses, helping you identify and prioritize fixes. middleBrick's continuous monitoring can alert you if new endpoints are deployed without proper authorization controls.
Remediation
Fixing Cwe 384 requires implementing robust, consistent authorization controls throughout your API. Here are code-level remediation strategies with examples:
1. Implement Centralized Authorization Middleware
Create a middleware layer that enforces authorization before reaching your business logic:
// Express.js authorization middleware
const authorize = (requiredPermission) => {
return (req, res, next) => {
const user = req.user;
if (!user) {
return res.status(401).json({ error: 'Authentication required' });
}
if (!user.hasPermission(requiredPermission)) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
next();
};
};
// Usage in routes
app.get('/admin/users',
authenticate,
authorize('admin:read'),
(req, res) => {
// Only users with 'admin:read' permission reach here
res.json(adminService.getAllUsers());
}
);
2. Resource-Based Authorization with Ownership Verification
Always verify resource ownership before returning data:
// Secure resource access
async function getUserProfile(req, res) {
const { userId } = req.params;
const authenticatedUserId = req.user.id;
// Verify ownership
if (userId !== authenticatedUserId) {
// Check if user has permission to view this profile
if (!await canUserViewProfile(req.user, userId)) {
return res.status(403).json({
error: 'Access to this resource is forbidden'
});
}
}
const profile = await profileService.getById(userId);
if (!profile) {
return res.status(404).json({ error: 'Profile not found' });
}
res.json(profile);
}
// Helper function for complex authorization
async function canUserViewProfile(user, targetUserId) {
// Check if user is admin or has explicit permission
return user.role === 'admin' ||
await user.hasPermission('profile:view-any');
}
3. Principle of Least Privilege
Grant users only the permissions they absolutely need:
// Define granular permissions
const permissions = {
'user:read-own': { description: 'Read own user profile' },
'user:read-any': { description: 'Read any user profile (admin)' },
'user:write-own': { description: 'Update own user profile' },
'user:write-any': { description: 'Update any user profile (admin)' },
'admin:create': { description: 'Create admin users' }
};
// Role definitions
const roles = {
'user': ['user:read-own', 'user:write-own'],
'manager': ['user:read-own', 'user:read-any', 'user:write-own'],
'admin': ['user:read-any', 'user:write-any', 'admin:create']
};
// Check permissions
function hasPermission(user, requiredPermission) {
return user.permissions.includes(requiredPermission);
}
4. Database-Level Authorization
Implement row-level security in your database queries:
// Using parameterized queries with ownership check
async function getOrders(userId, requestingUserId) {
const query = `
SELECT * FROM orders
WHERE user_id = $1
AND (
$2 = $1 OR
EXISTS (
SELECT 1 FROM user_roles
WHERE user_id = $2 AND role = 'admin'
)
)
`;
const params = [userId, requestingUserId];
return db.query(query, params);
}
5. API Gateway Authorization
Use API gateway policies for centralized authorization:
# OpenAPI 3.0 security schema
definition:
openapi: 3.0.0
paths:
/admin/users:
get:
security:
- bearerAuth: []
x-amazon-apigateway-auth:
type: aws_iam
authorizer:
type: token
authorizerResultTtlInSeconds: 300
identitySource: method.request.header.Authorization
managedBy: aws
6. Regular Authorization Audits
Periodically test your authorization controls:
// Automated authorization test
async function testAuthorization() {
const users = await createTestUsers([
{ role: 'user', email: '[email protected]' },
{ role: 'admin', email: '[email protected]' }
];
// Test admin endpoint with user role
const adminResponse = await request(app)
.get('/admin/users')
.set('Authorization', `Bearer ${users.user.token}`);
if (adminResponse.status !== 403) {
throw new Error('Authorization bypass detected!');
}
console.log('Authorization tests passed');
}
Remember that authorization is an ongoing process. New endpoints, roles, and features can introduce authorization gaps. Implement continuous monitoring with tools like middleBrick to catch these issues before they become security incidents.
Frequently Asked Questions
How does Cwe 384 differ from broken authentication?
Cwe 384 (Missing Authorization) and broken authentication are distinct but related security issues. Authentication verifies who you are (identity), while authorization verifies what you're allowed to do (permissions). You can have perfect authentication but still suffer from Cwe 384 if your system doesn't properly check permissions after verifying identity. For example, a system might correctly authenticate that you're user ID 123, but if it then allows you to access any user's data without checking ownership, that's a Cwe 384 authorization failure, not an authentication problem.
Can middleBrick detect all instances of Cwe 384 in my API?
middleBrick provides comprehensive automated scanning for Cwe 384 through its BOLA/IDOR and Property Authorization checks, but no scanner can guarantee 100% detection. middleBrick tests your API's unauthenticated attack surface by attempting to access resources across different user contexts and manipulating request parameters. However, complex authorization logic that depends on business rules, database state, or external services may require additional manual testing. middleBrick is most effective as part of a defense-in-depth strategy that includes code review, manual penetration testing, and continuous monitoring.