Skip to main content
blog

Access Control Testing: Principles, Vulnerabilities & Tools

December 30, 2024 · 1564 words · 11 min read

Access Control Testing: Principles, Vulnerabilities & ToolsImage unavailableTry again
Table of Contents
Preparing narration.

Authentication answers one question: "Who are you?" Access control, also called authorization, answers the next one: "What are you allowed to do?"

That distinction matters every time an API returns a record, changes an account, or accepts an uploaded file. A request can come from a correctly signed-in user and still be forbidden. If the application checks only the login and forgets the permission check, the user may be able to read another person's data or call an admin-only endpoint.

This guide walks through the rules behind access control, the failures worth testing, and a practical way to turn those checks into regression tests. You can use the examples with a browser, an API client such as Postman, or an automated test runner.

What access control is checking

Every protected request has at least three parts: a subject, an action, and a resource. The subject might be a user or a service. The action could be reading, editing, deleting, or uploading. The resource is the thing being touched, such as an invoice, project, or user profile.

The server should make the permission decision from those parts. Do not trust a role, account ID, or permission flag that arrives only in the request body. A client can change it before the request reaches your application.

The useful test question is simple: if I change the identity, role, or resource ID in this request, does the server still make the right decision?

Principles that make permissions safer

Least privilege

Give each account only the permissions it needs for its job. A support user may need to view a ticket but not delete it. A customer may edit their own profile but not another customer's profile.

Least privilege reduces the damage caused by a stolen account. It also makes tests easier to reason about because every allowed action has a clear reason.

Separation of duties

Some operations should require more than one person or role. For example, the account that prepares a payment should not be the only account that can approve it. This limits what one compromised account can do by itself.

Roles and policies

Role-based access control, or RBAC, groups permissions into roles such as admin, manager, and user. It is useful when the rules are stable. Attribute-based access control, or ABAC, makes the decision from details such as the user, resource owner, location, or request time.

The name of the model matters less than the testable rule behind it. Write down which roles can perform which actions, then test both sides of every rule.

Common access control failures

Horizontal privilege escalation

This happens when one user can access another user at the same permission level. A classic example is changing /user/123 to /user/124 and receiving someone else's profile. The application authenticated you, but it failed to check that you own resource 124.

Vertical privilege escalation

This happens when a lower-privileged user can perform a higher-privileged action. A normal user should not be able to call an admin endpoint simply by discovering its URL or copying an admin request.

Insecure direct object references

An ID in a URL is not a permission check. IDs, filenames, and document keys are often useful clues during testing because changing one may expose another record. The server must verify access to the referenced object for every request.

Excessive permissions

Sometimes the application works exactly as coded, but the role has more access than it needs. Review the permission matrix as well as the implementation. A test that passes because a user can delete every record is not a success.

Unsafe file uploads

Upload endpoints need checks for file type, size, storage location, and later execution. Try permitted and forbidden extensions in a safe test environment, and verify that a rejected upload is not stored or served as executable content.

A practical testing workflow

Start with a small permission matrix. Put roles in one column, actions in another, and record the expected response for each combination. Include ownership in the matrix when a user should access only their own records.

Then capture one valid request for each protected operation. Keep the request body, path parameter, query parameter, cookie, and authorization header visible in your test notes. The permission decision can depend on any of them.

Test horizontal access

Sign in as user A and create or identify a resource owned by user B. Replay the request with user A's credentials and user B's resource ID. The server should reject it or return a response that does not disclose the protected data.

For example, compare requests for https://example.com/user/123 and https://example.com/user/124. A 200 response is not automatically a vulnerability, but receiving user B's private fields is a clear failure.

Test vertical access

Use a low-privilege account to call an administrative operation such as https://example.com/admin. Test the route directly, then test the same action through alternate HTTP methods or content types if the application supports them.

Do not stop after hiding an admin button in the UI. The API must enforce the rule too.

Test the request, not just the page

Browser tests can miss authorization bugs in background requests. Inspect the API calls made by the page and change one permission-relevant value at a time. Check the status code and the response body; an error status with sensitive data in the body is still a leak.

Test uploads and exports

Try a permitted file and then a forbidden extension such as .php instead of .jpg. Check where the file is stored and whether the resulting URL can be guessed. Apply the same care to export endpoints, because a download that is hidden from the UI may still be reachable directly.

Manual and automated checks

Manual testing is useful when you are discovering the permission model. A proxy such as Burp Suite or OWASP ZAP lets you edit requests and compare the server's decisions. Postman is handy for keeping a small set of role-specific requests, and tools such as Cypress or Playwright can exercise complete user flows.

Static analysis can find suspicious patterns in source code, such as hardcoded credentials or routes with missing middleware. Dynamic testing checks the running application, which is where configuration and service boundaries often change the outcome. Interactive analysis combines runtime behavior with code-level information.

Automation pays off after you have a known-good matrix. Save the expected result for every role and action, run it in CI, and keep a regression test for every authorization bug you fix. If your service is already handling real API traffic, Keploy's API test generator can capture authenticated requests and replay them as tests. Review captured tokens and redact secrets before storing the tests.

What to verify in a test result

An authorization test should verify more than a status code. Check that:

  • the response status matches the policy;
  • the body contains no fields from the protected resource;
  • the server does not reveal a useful difference between an existing forbidden record and a missing record, when that distinction matters; and
  • the denied request does not create, update, delete, or upload anything as a side effect.

Also test expired tokens, missing tokens, tokens issued for another audience, and a user whose role changed after the token was issued. Those cases often expose stale permission checks.

Keeping access rules maintainable

Centralize permission decisions where practical so that different endpoints do not slowly develop different interpretations of the same role. Log denied access with enough context to investigate, but do not put passwords, raw tokens, or private request bodies in the logs.

Review permissions when a feature changes. A new endpoint, background job, export button, or service-to-service call can create a second path to the same data. The UI is only one path.

One caveat from working with API tests: a large number of passing requests can create false confidence if every request uses an admin token. Keep fixtures for the least-privileged roles too. They are the ones that prove the boundary exists.

Final checks

Access control is a server-side decision about a specific subject, action, and resource. Test ownership changes, role changes, direct endpoint access, alternate request shapes, and side effects. Then keep those cases in the regression suite so the permission boundary does not disappear during the next refactor.

FAQs

How does Keploy assist in access control testing?

Keploy is an open-source testing platform that automates test generation for APIs. It captures API calls during runtime and helps validate access control policies by replaying these calls in test scenarios. Keploy’s features can identify misconfigurations in access permissions or API endpoints.

What’s the difference between authentication and authorization?

Authentication verifies a user’s identity (e.g., logging in with a username and password). Authorization determines what actions or resources a user is permitted to access.

How can DevSecOps integrate access control testing?

DevSecOps practices integrate security testing, including access control validation, into CI/CD pipelines. Tools like Keploy, OWASP ZAP, and automated test scripts can continuously verify access permissions during development.

How do access control mechanisms evolve with microservices architecture?

Microservices often rely on decentralized components. Access control involves:

  • API gateways for centralized policy enforcement.
  • Service-level policies (e.g., ABAC for inter-service communication).
  • Tools like Open Policy Agent (OPA) for flexible policy management.

How important is user feedback in refining access control policies?

Gathering user feedback on denied permissions or excessive restrictions helps refine access control rules, ensuring a balance between security and usability.

securitytestingauthorizationwebdev