Broken Access Control

Authorization FlawsAccess Control MisconfigurationACL Bypass

Broken Access Control at a glance

What it is: Authorization is missing or incorrect, allowing attackers to perform actions or access data they should not.
Why it happens: Leads to data breach, privilege escalation, and unauthorized actions
How to fix: Enforce authorization server side for every resource and action; Use resource based policies and centralized checks; Never trust client supplied roles or IDs, and whitelist updatable attributes

Overview

Broken access control occurs when authorization checks are missing, inconsistent, or enforce the wrong principal. This includes endpoints with no role checks, object level permissions that are not validated, misuse of client provided claims, mass assignment of privileged fields, and misapplied method level security. Attackers exploit these gaps to access or manipulate data they should not reach.

sequenceDiagram participant Browser participant App as App Server participant DB as Database Browser->>App: POST /admin/disable-user {userId: 123} App->>DB: disable user 123 (no role check) DB-->>App: success App-->>Browser: 200 OK note over Browser: Admin action performed without authorization
A potential flow for a Broken Access Control exploit

Where it occurs

Common places are admin endpoints missing middleware, object detail endpoints that accept ids without ownership checks, APIs that accept tenant or team ids without membership verification, controllers that mass assign attributes, and code that trusts client side roles or unsigned tokens.

Impact

Impact ranges from disclosure of sensitive data to full privilege escalation. A single missing check on a high impact endpoint can allow account takeover, mass data export, or manipulation of financial or product state.

Prevention

Adopt a deny by default model. Enforce authorization checks server side for both coarse grained roles and fine grained resource ownership. Use framework or language best practices for method level guards and resource policies. Avoid mass assignment, and treat any attribute that changes privileges as admin only. Validate tokens and claims cryptographically and map them to server side authoritative records.

Examples

Switch tabs to view language/framework variants.

Spring, service method exposed without @PreAuthorize

Controller calls a service method that assumes the controller checked roles. If any other caller reaches the service, unauthorized actions occur.

Vulnerable
Java • Spring Boot — Bad
import org.springframework.web.bind.annotation.*;
@RestController
class UserAdminController {
  @PostMapping("/promote")
  public String promote(@RequestParam Long id) {
    userService.promoteToAdmin(id); // BUG: no @PreAuthorize
    return "ok";
  }
}

@Service
class UserService{
  public void promoteToAdmin(Long id) { /* grants admin role */ }
}
  • Line 5: Service method performs privileged work without explicit method level guard

Authorization assumptions at the controller layer break when code is reused. Privileged logic must enforce authorization at the service boundary.

Secure
Java • Spring Boot — Good
import org.springframework.security.access.prepost.PreAuthorize;
@RestController
class UserAdminController {
  @PreAuthorize("hasRole('ADMIN')")
  @PostMapping("/promote")
  public String promote(@RequestParam Long id) {
    userService.promoteToAdmin(id);
    return "ok";
  }
}

@Service
class UserService{
  @PreAuthorize("hasRole('ADMIN')")
  public void promoteToAdmin(Long id) { /* grants admin role */ }
}
  • Line 4: Apply @PreAuthorize at controller and service to ensure enforcement

Use method level guards or central interceptors so authorization checks cannot be bypassed by calling services internally.

Engineer Checklist

  • Enforce authorization for every privileged route and resource

  • Scope DB queries by authenticated principal for object ownership

  • Use method level guards or resource policies, not only controllers

  • Whitelist updatable attributes, do not mass assign role flags

  • Verify tokens signatures and map claims to server side records

  • Add audit logs for high privilege actions and alert on unusual patterns

End-to-End Example

A multi tenant app exposes /teams/{id}/projects and returns projects for any id parameter. The attacker enumerates ids and harvests projects across tenants because the server does not check membership.

Vulnerable
JAVA
[HttpGet("/teams/{id}/projects")]
public IActionResult GetTeamProjects(int id) {
  // Bug: no membership check - any authenticated user can access any team's projects
  var projects = db.Projects.Where(p => p.TeamId == id).ToList();
  return Ok(projects);
}
Secure
JAVA
[HttpGet("/teams/{id}/projects")]
public async Task<IActionResult> GetTeamProjects(int id) {
  var userId = User.FindFirst("sub").Value;
  
  // Verify the authenticated user is a member of the team
  if (!await teamService.UserIsMemberAsync(userId, id)) {
    return Forbid();
  }
  
  var projects = db.Projects.Where(p => p.TeamId == id).ToList();
  return Ok(projects);
}

Discovery

Test if endpoints lack authorization checks by accessing admin/privileged functionality with regular user credentials.

  1. 1. Test unprotected admin endpoint

    http

    Action

    Access admin dashboard without admin role

    Request

    GET https://app.example.com/admin/dashboard
    Headers:
    Authorization: Bearer regular-user-token

    Response

    Status: 200
    Body:
    {
      "html": "<html><title>Admin Dashboard</title><h1>System Statistics</h1><p>Total Users: 125,430</p><p>Revenue: $12.5M</p>...",
      "note": "Admin dashboard accessible without admin role check"
    }

    Artifacts

    broken_access_control admin_dashboard_exposed missing_authorization
  2. 2. Test admin API without role check

    http

    Action

    Call admin-only API endpoint with regular user credentials

    Request

    GET https://app.example.com/api/admin/users
    Headers:
    Authorization: Bearer regular-user-token

    Response

    Status: 200
    Body:
    [
      {
        "id": 1,
        "username": "admin",
        "email": "admin@company.com",
        "role": "admin",
        "api_key": "sk_admin_xyz789"
      },
      {
        "id": 2,
        "username": "john",
        "email": "john@company.com",
        "role": "user"
      },
      "... (125,430 user records including admins and API keys)"
    ]

    Artifacts

    user_enumeration admin_account_disclosure api_key_exposure
  3. 3. Test write access without authorization

    http

    Action

    Attempt to modify system settings as regular user

    Request

    PUT https://app.example.com/api/admin/settings
    Headers:
    Authorization: Bearer regular-user-token
    Content-Type: application/json
    Body:
    {
      "maintenance_mode": true,
      "allow_signups": false
    }

    Response

    Status: 200
    Body:
    {
      "message": "Settings updated successfully",
      "settings": {
        "maintenance_mode": true,
        "allow_signups": false
      },
      "note": "System now in maintenance mode, new signups disabled"
    }

    Artifacts

    system_configuration_access service_disruption admin_functions_accessible

Exploit steps

Attacker with regular user account accesses admin functionality due to missing authorization checks, gaining full administrative control.

  1. 1. Access admin panel and enumerate privileges

    Explore admin functionality without admin role

    http

    Action

    Access admin endpoints to map available privileged functions

    Request

    GET https://app.example.com/admin/functions
    Headers:
    Authorization: Bearer regular-user-token

    Response

    Status: 200
    Body:
    {
      "available_functions": [
        "/admin/users - User management",
        "/admin/settings - System configuration",
        "/admin/billing - Payment and subscription management",
        "/admin/logs - Access and audit logs",
        "/admin/database - Database console"
      ],
      "note": "All admin functions accessible without authorization check"
    }

    Artifacts

    admin_function_enumeration unrestricted_access attack_surface_mapping
  2. 2. Delete user accounts and data

    Use admin delete function to remove accounts

    http

    Action

    Delete competitor or admin accounts without proper authorization

    Request

    DELETE https://app.example.com/api/admin/users/1
    Headers:
    Authorization: Bearer regular-user-token

    Response

    Status: 200
    Body:
    {
      "message": "User admin (ID: 1) deleted successfully",
      "deleted_user": {
        "username": "admin",
        "email": "admin@company.com",
        "role": "admin"
      },
      "cascade_deleted": "18 related records (sessions, API keys, audit logs)"
    }

    Artifacts

    admin_account_deleted data_destruction service_disruption
  3. 3. Access database console for direct manipulation

    Use admin database console without authorization

    http

    Action

    Execute arbitrary SQL queries via admin database interface

    Request

    POST https://app.example.com/admin/database/query
    Headers:
    Authorization: Bearer regular-user-token
    Body:
    {
      "query": "UPDATE users SET role='admin' WHERE id=9999; SELECT * FROM api_keys;"
    }

    Response

    Status: 200
    Body:
    {
      "query_results": [
        {
          "rows_affected": 1,
          "message": "User 9999 upgraded to admin"
        },
        {
          "results": [
            {
              "service": "Stripe",
              "key": "sk_live_51HxYz..."
            },
            {
              "service": "AWS",
              "key": "AKIAIOSFODNN7EXAMPLE",
              "secret": "wJalr..."
            },
            {
              "service": "SendGrid",
              "key": "SG.xYz789..."
            }
          ]
        }
      ]
    }

    Artifacts

    database_access privilege_escalation api_key_theft complete_compromise
  4. 4. Modify billing and steal payment information

    Access billing admin to view/modify payment data

    http

    Action

    Access customer payment information via unprotected admin billing endpoint

    Request

    GET https://app.example.com/admin/billing/customers
    Headers:
    Authorization: Bearer regular-user-token

    Response

    Status: 200
    Body:
    {
      "customers": 15430,
      "sample_records": [
        {
          "customer_id": "cus_ABC123",
          "name": "John Smith",
          "email": "john@company.com",
          "card_last4": "4242",
          "stripe_customer_id": "cus_...",
          "lifetime_value": 45000
        },
        "... (15,430 customer payment records)"
      ]
    }

    Artifacts

    payment_data_access customer_pii financial_information pci_compliance_violation

Specific Impact

The attacker exfiltrates internal project data from multiple teams. Sensitive information including project names, budgets, and owners is exposed. Depending on the data, this can enable corporate espionage or targeted phishing.

Remediation requires updating APIs to check membership, rotating any leaked secrets, and notifying impacted customers. Detection is slow because ordinary queries look similar to legitimate ones.

Fix

Check that the authenticated principal is authorized to access the resource before returning data. Centralize membership checks in a policy service and add tests and CI gates that fail on endpoints returning data for arbitrary ids.

Detect This Vulnerability in Your Code

Sourcery automatically identifies broken access control vulnerabilities and many other security issues in your codebase.

Scan Your Code for Free