In this article we will learn about what is the broken access control in ASP.NET Core, why is it important, and which vulnerabilities are covered under broken access control in ASP.NET Core. We will also learn about how attackers can exploit these vulnerabilities and how to fix ASP.NET Core code to mitigate risks related to vulnerabilities in broken access control in ASP.NET Core.
Table of Contents
Introduction to Broken Access Control

Let’s first understand what is access control. Access control is related to the authorization part of the application and is defined as a set of policies or mechanisms to provide control over the resources of the application. i.e. once the user has successfully logged into the application the access control mechanism is used to grant privileges to the resources that logged user is allowed to access.
Broken access control means that access control is not properly implemented or not functioning as desired so vulnerabilities get introduced into the application’s access control. Attackers can exploit these vulnerabilities to gain access to restricted resources.
The broken access control vulnerability is important to fix in our application code and also lately it has moved from the fifth position to the first position in the OWASP Top 10 Web Application Security Risks. The broken access control in ASP.NET Core is related to the vulnerabilities in the authorization part of the security code.
To fix this broken access control vulnerability in our application we enforce policies that prevent users from accessing resources or performing actions that are not permitted to the user i.e. users should not be able to view information or data which does not belong to them or is not authorized to access and also should not be able to perform non-permitted actions (like add, modify, delete, etc.) on the data.
The broken access control in the OWASP top 10 elaborates on the possible vulnerabilities in the authorization code or configuration that can allow an attacker to exploit the vulnerability to access restricted information and modify or delete that information. It even lists the ways how attackers can exploit the vulnerabilities in web applications by tampering with URLs, cookies, security tokens or page data to gain access to the restricted information or execute actions that they are not allowed to perform.
Broken Access Control Vulnerabilities
As per OWASP, the common access control vulnerabilities that are possible in the code and included under broken access control are as follows
- Not implementing the principle of denial by default i.e. access to restricted information or actions should be by default not allowed for anyone and should be enabled on a need basis for a specific user, user role or group i.e. restricted information should not be available to all users by default and then you disable it for the users who are not allowed to access it. To make it more clear this vulnerability points to a policy violation during the creation of a new user where the policy states that a new user by default should not have any access to the restricted data instead admin should explicitly allow the functions that are allowed to be accessed by the user.
- Getting access to the restricted resource or information or performing restricted action on the data by bypassing the access control mechanism of the application by manipulating the URL of the applications i.e. URL tampering that involves modification of the URL parameters, modification of the HTML page, or by using an attack tool to modify the HTTP request being sent to the application.
- Getting access to the details or data belonging to some other user by making use of the unique identifier of the data of the other user. i.e. attackers can modify the input unique identifier of the data to the request to access data belonging to other users.
- By some means changing the privileges assigned to the user so that it is able to get the higher privileges in the application i.e. either acting as an authenticated & authorized logged-in user without performing a successful login or a normal standard user gaining the elevation to an admin user.
- Exploiting the vulnerabilities in the security token used by the application i.e. replaying or tampering with the most popularly used JSON Web Token (JWT) access token or a cookie or hidden field to gain access to the restricted data or actions which are not allowed to the user.
- Misconfiguration in CORS (Cross-Origin resource sharing) allows the untrusted or unauthorized origins (websites) to gain access to the application API and enable attackers to trick users into performing actions without their knowledge.
- By some means force browsing to the authenticated or restricted pages by unauthenticated & unauthorized users impersonating an authenticated & authorized user or standard users impersonating an admin user.
- Misconfiguration or missing access control in security for HTTP methods PUT, POST & DELETE allows unauthorized users or attackers to gain access to the restricted application API by exploiting the missing access control configuration.
Sample Application for Demonstration
Here is the link to the ASP.NET Core Web Application that will the used for the demonstration of the vulnerabilities and fixes related to broken access control in ASP.NET Core.
Below is the list of the features that are provided in the ASP.NET Core Web Application
- The authentication has been implemented using Identity
- The authorization has been implemented using Identity Roles. Two default roles have been provided, Administrator and Standard User.
- The default user registration has been modified to capture the role of the user.
- UI has been provided to create & view Identity roles and this functionality can be accessed only by users with an Administrator role.
- The blog page has been provided for users to create & view details of the Blog articles created by the users. All the users can create & view the details of the blog articles created by them i.e. logged-in users cannot view the blog article details belonging to other users.
You can download the source code from the GitHub link provided above and once downloaded you will have to run the migrations. You can add migrations & update the database by executing the below commands in the package manager console.
add-migration FirstMigration update-database
Once migrations are successfully created then you can run the application. After running the application you will have to register a minimum of 2 new users one with a role administrator and another with a role Standard User. The user with the administrator role will have access to roles functionality and Posts functionality will be allowed to all the users but post data belonging to another user cannot be accessed.
For demonstration purposes, I have created 2 new users one with the administrator role sanjay@procodeguide.com & other with standard user role support@procodeguide.com
Vulnerabilities related to Broken Access Control in ASP.NET Core
So far we have discussed the vulnerabilities included in the broken access control and covered details of the sample application prepared for demonstration now let us understand how these vulnerabilities get introduced into the application code, how attackers exploit these vulnerabilities and how to identify & fix these vulnerabilities related to broken access control in ASP.NET Core.
Insecure Direct Object References
This vulnerability deals with a malicious user or attacker accessing restricted data or is able to delete that data as well. When we insert data into the database then we get a unique identifier that gets connected to the data to retrieve or modify this data in the database. Sometimes we end up using an incremental sequence number for these unique IDs which makes it very easy for users to guess the unique Ids that will be present in the database.
Though in the application views we will be displaying only the records that belong to the user. But for a malicious user, it might be possible to locate these unique identifiers in your request URL or body and exploit that by replacing the unique Id in the request with any number that does not belong to the user. Now if your application has not implemented the access controls properly then malicious users can end up accessing these records and even delete those records.
Let’s check how this vulnerability exists in our code and how we can fix this broken access control in ASP.NET Core by implementing proper access controls.
Attack Scenario
Here are steps on how attackers can gain access to the post-related data of another user
1. Run the application that was downloaded. Then log in as user sanjay@procodeguide.com & create a couple of posts-related records by navigating to the screen Post->Create. This will create records in the Posts that belong to the user sanjay@procodeguide.com as shown below

2. Next log in as user support@procodeguide.com & again create a couple of post-related data by navigating to the screen Post->Create. This will create records in the Posts that belong to the user support@procodeguide.com as shown below

3. Now for the user support@procodeguide.com 2 records are available for posts with Id 3 & 4.
4. Navigate to the post view details page for one of the post records as shown below

5. For an attacker it won’t be difficult to figure out that post IDs are generated as incremental numbers and definitely there should be records with Id 1 & 2 for some users. Also, the attacker will note that the post Id is being appended to the page URL so the attacker will try to tamper URL by changing the Id to 1 or 2 and request the data as shown below

As you can see from the above screen the user support@procodeguide.com is able to access the post record from the data belonging to the user sanjay@procodeguide.com. so the above bug shows that the view post details page in the application is vulnerable and can be exploited by Insecure Direct Object Reference.
Let’s see how we can fix this vulnerability related to Insecure Direct Object Reference related to broken access control in ASP.NET Core to ensure that any user cannot access the data belonging to another user.
Fixing Insecure Direct Object References
To fix this insecure direct object reference vulnerability related to the broken access control in ASP.NET Core we will introduce a policy for authorization that will check if the user id of the post being requested is the same as the authenticated logged-in user requesting these post details. I.e. We will introduce an authorization policy that will not allow the logged-in user to view post details belonging to other users.
Add Authorization Policy Handlers
First, add the handler for the authorization policy to match the user id of the post with the logged-in user.
Add the below classes under the folder AuthorizationHandlers – AuthorizationHandlers\IsPostOwnerRequirement.cs & AuthorizationHandlers\PostOwnerAuthorizationHandler.cs
public class IsPostOwnerRequirement : IAuthorizationRequirement { //empty class }
public class PostOwnerAuthorizationHandler : AuthorizationHandler<IsPostOwnerRequirement, PostEntity> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IsPostOwnerRequirement requirement, PostEntity resource) { if (context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value == resource.CreatedBy) { context.Succeed(requirement); } else { context.Fail(); } return Task.CompletedTask; } }
The above authorization policy is comparing the user id of the post with the user id of the logged-in user and if they match then it set the successful flag else it set the flag as failed.
Register Authorization Policy Handlers
We will register the policy handlers classes in the startup in the main function of the Program.cs file. We will add the below code to register the policy handlers in the main function.
builder.Services.AddAuthorization(options => { options.AddPolicy("IsPostOwnerPolicy", policy => policy.Requirements.Add(new IsPostOwnerRequirement())); }); builder.Services.AddSingleton<IAuthorizationHandler, PostOwnerAuthorizationHandler>();
The above code will register the authorization policy as a service in the dependency injection container.
Use Authorization Policy Handlers
Now that we have defined the authorization policy and also registered the same as a service in the startup we will make use of this policy in Posts to plug the insecure direct object reference vulnerability. We will refactor the Services\PostsService.cs file to make use of the authorization policy. We have made the below changes to the PostService class
public class PostsService : IPostsService { IPostsRepository? _postRepository = null; private readonly IAuthorizationService _authorizationService; private readonly IHttpContextAccessor _httpContextAccessor; public PostsService(IPostsRepository postRepository, IAuthorizationService authorizationService, IHttpContextAccessor httpContextAccessor) { _postRepository = postRepository; _authorizationService = authorizationService; _httpContextAccessor = httpContextAccessor; } //Remaining code have been removed for readability public Post GetById(int id) { PostEntity postEntity = _postRepository.GetById(id); var authorizationResult = _authorizationService.AuthorizeAsync (_httpContextAccessor.HttpContext.User, postEntity, "IsPostOwnerPolicy"); Post post = new Post(); if (authorizationResult.Result.Succeeded) { post.Id = postEntity.Id; post.Title = postEntity.Title; post.CreatedOn = postEntity.CreatedOn; post.Description = postEntity.Description; } return post; } }
In the above service code, we have injected the Authorization policy service and HttpContext service to implement the check for authorization policy in the Posts Service. The HttpContext will give us the object for the logged-in user.
Run & Test the Authorization Policy
Now let’s build & run the application to verify whether the newly added authorization policy is able to fix the insecure direct object reference vulnerability related to broken access control in ASP.NET core.
We will test the same scenario that we discussed in the attack scenario we will log in as user support@procodeguide.com and try to access the post details using the URL path Post/Details/1 and this should not return any data as per the newly added authorization policy code.

As shown in the above figure now logged user is not able to access the post details data belonging to another user.
Missing Authorization
This vulnerability deals with a malicious user accessing restricted actions due to missing or incomplete configuration for authorization code.
Let’s check how this vulnerability exists in our code and how we can fix this missing configuration vulnerability related to broken access control in ASP.NET Core by implementing proper access controls.
Attack Scenario
Here are steps on how attackers can gain access to the Roles page in the application
1. Run the application & log in as user sanjay@procodeguide.com
2. Since sanjay@procodeguide.com is a user with an administrator role so Roles menu is available for this user. Using roles menu administrator can view or create a role related to the application as shown below

3. Next login as user support@procodeguide.com & you can see that since this user is not an administrator so roles menu is not available for this user as shown in the below screen.

4. The user support@procodeguide.com cannot access the roles page as per authorization defined in the application but now somehow this user gets hold of the roles page URL and requests that URL directly in the browser.
5. After the user request the URL then we get the below screen

As you can see from the above screen though the user support@procodeguide.com is not allowed but is able to access the role screen and create a new role as well.
Let us see how we can fix this vulnerability related to Missing or incomplete Configuration in broken access control in ASP.NET Core to ensure that any user cannot access the restricted actions.
Fixing Missing Authorization
To fix this missing configuration vulnerability related to the broken access control in ASP.NET Core we will introduce a missing role check in the authorize attribute in the RoleController.cs.
What we analysed is we have added the authorize attribute in RoleController and also we have added a role check for the menu in the _Layout.cshtml but we have missed the specification of the Administrator role in the authorize attribute in the RoleController.cs
Adding missing authorization role check
We will refactor the Controllers\RoleController.cs file to add the missing role check in the authorize attribute. We made the following changes to the RoleController.cs file
[Authorize(Roles ="Administrator")] public class RoleController : Controller { //Remaining Code has been remove for readability }
By adding the missing configuration for the Administrator role in the authorize attribute in RoleController.cs we specify that all the actions in RoleController are allowed only for users with the role of administrator
Run and Test the Authorization Configuration
Now let us build & run the application to verify whether the newly added missing authorization configuration is able to fix the missing authorization vulnerability related to broken access control in ASP.NET core.
We will test the same scenario that we discussed in the attack scenario we will log in as user support@procodeguide.com and try to access the roles URL and this should not return the roles page as we have added the missing authorization fix

As shown in the above figure now the user support@procodeguide.com who does not have the administrator role is not able to access the role page to create & view roles.
CORS Misconfiguration
The browser by default implements the same origin policy which states that a server cannot make a request to a different domain than the one serving the page. This restriction protects sensitive data from malicious origins i.e. sites.
But sometimes there is a need to override this same-origin policy and allows other domains to access the API. This is not a security feature in fact it reduces the security of the server by allowing other domains to access the API.
CORS misconfiguration relates to the broken access control in ASP.NET Core in a way that when you are overriding the same-origin policy then care should be taken to allow only the specific allowed sites instead of allowing all the sites so that requests from other than allowed sites are rejected.
In this way, we have better control over the security by allowing only the trusted sites to access the API and by restricting all other sites we prevent malicious sites from accessing the API.
If by mistake you do not configure the CORS properly i.e if you misconfigure CORS then you are introducing a vulnerability in the application that can be exploited by the attackers to gain access to API
The below code will override the same-origin policy and allow access to all the other domains
app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod());
The above configuration for CORS to allow all methods & origins should be avoided until and unless you are working on a public API that is meant to be accessed by all.
Below is the code that configures only the specific allowed domain for access to the API
app.UseCors(options => options.WithOrigins("http://www.allowed-domain.com").AllowAnyMethod());
As far as security is concerned you should follow the rule of no access by default and allow access only to the required resources by the authorized users.
Directory Browsing
Directory browsing in the ASP.NET Core application should not be allowed i.e. if the user has requested the URL of some folder path then the list of files available in the folder should not be displayed in the browser.
For example, if a user requests the URL of an image or script folder then the list of the images or scripts available in the folder should not be directly displayed in the browser.
Summary
We learned about the critical vulnerabilities under broken access control in ASP.NET core. Also, we covered how an attacker can exploit these vulnerabilities and how an ASP.NET Core developer can identify & mitigate these vulnerabilities related to broken access control in ASP.NET Core.
The insecure direct object reference and authorization misconfiguration are the most critical to identify and mitigate as they posses the risk of exposing restricted data and actions.
Please provide your suggestions & questions in the comments section below
References – OWASP Top 10 & Broken Access Control
Download Source Code
Here you can download the complete source code for this article demonstrating how to mitigate vulnerabilities related to broken access control in ASP.NET Core Application.
You can also check my other article related to how to configure Security in ASP.NET Core
- ASP.NET Core Identity – Getting Started
- ASP.NET Core Identity Claims-based Authorization
- ASP.NET Core Identity Identity Roles-based Authorization
- Implement Cookie Authentication in ASP.NET Core
- Secure Applications with OAuth2 and OpenID Connect in ASP.NET Core 5 – Complete Guide
Hope you found this article useful. Please support the Author
