CWE-285: Improper Authorization
Overview
Improper Authorization occurs when an application fails to enforce or incorrectly implements authorization checks, allowing users to access resources or perform actions beyond their intended permissions.
OWASP Classification
A01:2025 - Broken Access Control
Risk
High: Attackers can access, modify, or delete data, escalate privileges, or perform unauthorized actions, leading to data breaches, loss of integrity, or system compromise.
Remediation Steps
Core principle: Never infer authorization from authentication, role, or prior checks; every security-sensitive action must be explicitly authorized against the specific resource and operation being performed.
Locate the missing or improper authorization in your code
- Review the flaw details to identify the specific file, line number, and code pattern
- Identify the protected resource or operation lacking authorization (admin function, user data access, sensitive operation)
- Trace the data flow: is there ANY authorization check before the operation
- Determine the risk: what can an unauthorized user access or do (view data, modify resources, escalate privileges)
Enforce authorization on every request (Primary Defense)
- Check user permissions for every resource and action: Never assume authorization based on previous checks or URL hiding
- Use centralized authorization logic or frameworks: Implement authorization middleware, decorators, or service - don't scatter checks
- Enforce server-side checks: Never rely on client-side enforcement (hidden buttons, disabled fields) - always validate on server
- Pattern:
if (!currentUser.hasPermission(REQUIRED_PERMISSION)) return 403 Forbidden - Check both function-level and data-level: Verify user can call the function AND access the specific resource
Apply the principle of least privilege
- Grant users only the permissions they need: Start with no permissions, explicitly grant only required access
- Regularly review and update access controls: Quarterly access reviews, revoke permissions when roles change
- Default deny: Require explicit permission grant rather than defaulting to allow
- Separate admin and user roles: Don't give regular users admin permissions "temporarily"
Implement RBAC or ABAC for authorization management
- Use Role-Based Access Control (RBAC): Define roles (USER, ADMIN, MODERATOR), assign permissions to roles, assign roles to users
- Use Attribute-Based Access Control (ABAC): For complex scenarios, use attributes (user department, resource classification, time of day)
- Avoid hard-coding authorization: Don't scatter permission checks throughout code - centralize in authorization service
- Use framework features: Java
@PreAuthorize, .NET[Authorize], Django@permission_required, Express middleware
Monitor and audit access attempts
- Log all access attempts and permission changes (successful and failed authorization, role assignments, permission grants)
- Alert on suspicious or unauthorized activity (repeated 403 errors, privilege escalation attempts, unusual access patterns)
- Track authorization failures by user and resource (identify potential attacks or misconfigured permissions)
- Review audit logs regularly for security incidents
Test the authorization fix thoroughly
- Test with different user roles (guest, user, admin)
- Verify unauthorized users get 403 Forbidden for protected resources
- Test direct URL access to admin functions (bypassing UI)
- Test API endpoints with missing or invalid credentials
- Verify legitimate functionality works for authorized users
- Re-scan with security scanner to confirm the issue is resolved
Dynamic Scan Guidance
For guidance on remediating this CWE when detected by dynamic (DAST) scanners:
- Dynamic Scan Guidance - Analyzing DAST findings and mapping to source code
Common Vulnerable Patterns
- Missing or inconsistent authorization checks
- Relying on client-side enforcement
- Using predictable resource identifiers without ownership checks
Missing Authorization Check on Privileged Endpoint (Python Flask)
# No authorization check
@app.route('/admin')
def admin_panel():
return render_admin_panel() # Anyone can access!
Secure Patterns
Role-Based Access Control Check (Python Flask)
# Enforce authorization
@app.route('/admin')
def admin_panel():
if not current_user.is_authenticated:
abort(401) # Unauthorized
if not current_user.is_admin:
abort(403) # Forbidden
return render_admin_panel()
Why this works:
- Validates user role/permissions server-side before granting access to privileged functionality
- Prevents unauthorized users from accessing admin panels, sensitive data, or privileged operations
- Returns 403 Forbidden when authenticated user lacks required permissions (vs 401 for unauthenticated)
- Enforces principle of least privilege by checking explicit authorization, not just authentication
- Cannot be bypassed through client-side manipulation or direct URL access
Language-Specific Guidance
- C# - [Authorize] attribute, ClaimsPrincipal, policy-based authorization