The goal of this article is to explore the subject of access control and how you can provide appropriate security for your websites. First, we will briefly address what broken access control is. Then, we will use examples to illustrate what broken access control looks like and what vulnerabilities get targeted. Finally, we'll give you several mitigating solutions for those vulnerabilities.
Without further ado, let's jump right in.
What Is Access Control?
First, we'll start by laying out the basics of what access control is.
Access control, also commonly referred to as authorization, is a set of mechanisms and policies that manage access over resources. Usually, once the server has determined your credentials using an authentication mechanism, it will then grant or restrict what resources you can access in the system. Also, the authorization infrastructure serves as the backbone for user tracking resource monitoring.
Furthermore, users of most platforms usually fit into more than one role, which means that access control complexity rises exponentially.
It's important not to confuse authentication with authorization. According to Microsoft, "authentication is the process of determining a user's identity. Authorization is the process of determining whether a user has access to a resource."
Properly implementing a solid and secure access control system is complex and tricky since it's closely tied to the system architecture. Because of this, the task of developing an access control mechanism for applications can be daunting, even for experienced engineers. In fact, depending on the scale and complexity of the system, an adequate solution could be to implement a third-party library or a simple authentication, or perhaps even a combination of the two.
Explaining Broken Access Control
Now that we've explained what access control is, that gives a better idea of what broken access control refers to. Simply speaking, broken access control describes the vulnerabilities that exist in a system's access control.
As explained before, any breach of the access control mechanism can be catastrophic for a system. Given that a successful attack could provide an attacker with free rein over your platform, it is crucial to address any vulnerabilities that exist.
Common Broken Access Control Vulnerabilities
Let's now explore what a common broken access control vulnerability looks like.
In this post, we covered insecure IDs, path traversal, file permission, and client caching attacks. But here's a brief refresher.
Insecure IDs Vulnerability
A majority of modern websites use some type of ID or index to refer to data quickly, and this works well for most situations. That said, if these IDs are too simple for someone to figure out, whether that's by hand or by brute force, then you'll be faced with a security problem.
To illustrate, imagine you have a profile page section where the user profile is displayed. Then, this URL retrieves our user profile: https://www.mywebsite.com/profile?id=123
If I decide to manually alter the number in the query string and there's no active access control that will validate my request, I can access any profile I want.
Path Traversal Vulnerability
The concept of path traversal refers to a user's capacity to freely navigate a filesystem's directory tree.
A system that doesn't have proper access control has the potential of being vulnerable to path traversal exploits and could let attackers access restricted resources that are in the server. This scenario might occur when the path of a resource that the system is letting be retrieved is able to be changed and isn't validated properly.
As an example, please refer to the following URL: https://www.mywebsite.com/photos?file=user.png
If I changed "user.png" to "../../etc/passwd", for instance, then I could access the application secrets.
File Permission Vulnerability
File permission vulnerability relates to vulnerabilities in a server's permission mechanism in its filesystem.
Every web app has critical configuration files and resources that outsiders shouldn't have access to. But if the right configuration policies aren't in place, a hacker can target these files and then overtake the entire platform.
Here's an example of someone trying to get into a file that should be unavailable to them: https://www.mywebsite.com/photos?file=../../gradle.json
Client Caching Vulnerability
Vulnerabilities involving client caching can be difficult to address. Instead of attacking remotely, a hacker physically takes over a user's computer. That means the hacker is able to use cached pages, session credentials, and browser data that already exist and have been authenticated.
Once the attacker has done this, they're able to quickly gain access to the user's information.
Addressing Broken Access Control
All things considered, many variables can make tackling access control vulnerabilities either a straightforward process or an incredibly complex ordeal. The complexness of your platform, your architecture, and data sensitivity are but a few of them. That said, the first step should always be to implement a proper authentication mechanism.
As explained in the Microsoft official documentation site, "in ASP.NET Core, authentication is handled by the IAuthenticationService, which is used by authentication middleware. The authentication service uses registered authentication handlers to complete authentication-related actions."
To implement authentication, we will be using the Auth0 SSO service to provide a third-party solution that is robust and reliable.
First, we have to go to the Auth0 website and register our application. You'll have to sign up for an Auth0 account if you don't already have one.
Once in the dashboard, go to the Applications section and click on the Create application button. Then, input a name for your application and make sure to choose "Regular web applications" as the application type.
Lastly, click the Create button.
After creating the application, go to the Settings tab and get your Auth0 "domain" and "client ID." Then, set "Allowed callback URLs" to "https://localhost:9595/callback" and set "Allowed logout URLs" to "https://localhost:9595/".
The first URL will indicate to Auth0 where to redirect the user after authentication, while the second URL indicates where to redirect the user after logout.
Finally, save your changes.
Now, go to your project's appsettings.json file and set the following:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Auth0": {
"Domain": "YOUR_DOMAIN",
"ClientId": "YOUR_CLIENT_ID"
}
}
Replace YOUR_DOMAIN and YOUR_CLIENT_ID with the corresponding values you copied from the Auth0 dashboard.
Implementing the Authentication SDK
Now that Auth0 has been set up, you can implement the authorization changes so your application takes advantage of it.
First, install the Auth0 ASP.NET Core Authentication SDK by running the following command:
dotnet add package Auth0.AspNetCore.Authentication
This library lets you easily integrate OpenID Connect–based authentication into your website quickly and painlessly.
Now let's modify our application code to support the authentication mechanism.
Go to the Program.cs file and update its contents:
// ADDED CODE
using Auth0.AspNetCore.Authentication;
var builder = WebApplication.CreateBuilder(args);
// ADDED CODE
builder.Services
.AddAuth0WebAppAuthentication(options => {
options.Domain = builder.Configuration["Auth0:Domain"];
options.ClientId = builder.Configuration["Auth0:ClientId"];
});
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment()) {
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
// ADDED CODE
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
Here we first added a reference to the Auth0.AspNetCore.Authentication. Then we invoked the method AddAuth0WebAppAuthentication() with Auth0 as domain and our client ID. Finally, we called the UseAuthentication() method to allow the authentication middleware to do its work.
Implementing Login
To implement a login mechanism, add an AccountController.cs class to the Controllers folder and add the following code:
using Microsoft.AspNetCore.Authentication;
using Auth0.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
public class AccountController : Controller {
public async Task Login(string URLtoReturn = "/") {
var properties = new LoginAuthenticationPropertiesBuilder()
.WithRedirectUri(URLtoReturn)
.Build();
await HttpContext.ChallengeAsync(Auth0Constants.AuthenticationScheme, properties);
}
}
This class defines a controller to handle standard user functions.
Finally, make sure to add a login link redirecting to this controller, and voilà, you have a login form.
It's important to remember that even though the authentication groundwork has been done, you have not yet protected any method with it. To do that, you simply need to add the [Authorize] directive over it and then ASP will do the rest for you.
Tackling Broken Access Control Vulnerabilities
We need to make a few adjustments to our platform to tackle the specific vulnerabilities stated above.
Insecure IDs: You can easily resolve insecure IDs by implementing GUIDs as IDs. You'll have to develop your system early on with this vulnerability in mind. IDs that belong to sensitive resources have to be unique and cloaked.
Path traversal: Addressing path traversal mitigation requires you to validate user inputs and limit access to critical resources. Thankfully, there's not much you have to do to implement proper path traversal policies because libraries like Spring Security are robust.
File permission: In terms of file permission, you don't need to do a lot to stay secure, unless you have to play with server permissions and add features that have to do with file manipulation. Despite this, it's best to talk to your server manager if needed.
Client caching: With client caching, the best solution is also the simplest one: You'll be okay as long as you're not storing sensitive user information on the client browser. But if you have to explore sophisticated features, be sure to use async validations and HTML meta tags to confirm authority when the page loads.
Final Thoughts
While building solid web applications, we are constantly making tiny decisions that can affect the stability and security of a business. We depend on an extensive understanding of development, infrastructure, and security fundamentals to carry out this responsibility properly.
Furthermore, few things are as critical as ensuring that our platforms are stable and that our users' information is secure. Doing so is a process that's getting more involved and more sensitive. To illustrate, SD Times says that broken access control was the highest vulnerability in OWASP's top 10 of 2021.
Developers should be concerned about this. But despite all its complexity, delivering effective access control can be fairly straightforward, as outlined in this post.
This post was written by Juan Reyes. Juan is an engineer by profession and a dreamer by heart who crossed the seas to reach Japan following the promise of opportunity and challenge. While trying to find himself and build a meaningful life in the east, Juan borrows wisdom from his experiences as an entrepreneur, artist, hustler, father figure, husband, and friend to start writing about passion, meaning, self-development, leadership, relationships, and mental health. His many years of struggle and self-discovery have inspired him and drive to embark on a journey for wisdom.