Understanding the fundamentals of access control and authorization is one of the essential skills for any respectable developer. Whether you’re a developer working with security-sensitive applications or a security enthusiast who wants to expand your knowledge, security is an essential part of using the modern web.
This article aims to explore the subject of access control and help you improve your ability to ensure adequate security for your platforms.
First, we’ll briefly define broken access control. Then, we’ll illustrate, with examples, what broken access control looks like and the vulnerabilities it targets. Finally, we’ll propose some mitigating methods for those vulnerabilities.
Before we dive into the subject, we want to emphasize that this article is written specifically for Angular developers. Therefore, please follow this link if you're not an Angular developer or haven't yet worked with it.
Having said that, you don't have to know Angular to benefit from this article. The explanations apply to any technology and will ultimately help you understand the subject better.
Fastest Angular Intro
Now, before we start, let's build our Angular project that will serve as the basis for this article. Don't worry — these instructions are extremely brief.
First, if you don't have Angular installed, let's install it. To achieve that, run the following command in the terminal.
npm install -g @angular/cli
Once that is done, create a project scaffold with the following command on the terminal.
ng new my-app
Finally, let's move into the newly created project folder and run the following command to start the server.
ng serve
And that's it. Go to localhost:4200 in your browser and see the fruit of your labor.
Pretty impressive, right?
What is Access Control?
OK, so what is access control in the first place?
Well, if you’ve seen a login page, you’ve already interacted with an implementation of access control.
Access control, generally known as authorization, is a set of mechanisms and policies that enforce access to resources.
Typically, once a server determines who you are through an authentication mechanism, it then grants or restricts what resources you have access to in the system.
Additionally, the authorization infrastructure serves as the backbone for user tracking and resource monitoring.
Adequately implementing a robust and secure access control system is a complex and tricky endeavor. Access control is, by nature, intimately tied to the system architecture.
Because users of most platforms often fit into more than one role, access control complexity can rise exponentially.
The challenge of developing robust access control can be intimidating, even for experienced engineers. Depending on the scale and complexity of your system, an adequate solution could mean implementing simple authentication, a third-party library, or even a combination of both.
Thankfully, JavaScript and Angular have popular and robust solutions like auth0 and JWT (JSON Web Tokens), to name a few.
What's Broken Access Control?
Very briefly, broken access control comprises the threats or vulnerabilities that can affect your access to your system's components.
A breach of access control can be disastrous for your system because it allows attackers to essentially gain free rain over your platform. Therefore, it’s crucial to address any vulnerabilities that exist.
Broken Access Control Vulnerabilities
Now that we understand the concept of broken access control, let's talk about actual examples of these attacks.
We will focus on insecure IDs, path traversal, file permission vulnerabilities, and client caching attacks.
Insecure ID's Vulnerability
Most relational databases that store data use IDs to identify resources. Moreover, modern websites use some form of ID or index to quickly and efficiently retrieve data. So, if your website allows users to input their ID for these sensitive resources and the IDs are easy to guess, you’re vulnerable to this attack.
Let's illustrate.
Imagine you have a profile page section that displays a user profile. Then the following URL retrieves the user profile.
https://www.mywebsite.com/profile?id=123
However, if I were to change the number in the query string manually and no active access control existed, I could access any profile.
To mitigate this vulnerability, we must address it early on in the development cycle.
First, IDs should not be easily guessable. Therefore, you must develop your system so that all IDs (or at least those belonging to sensitive resources) are both obfuscated and unique. You can do this by implementing globally unique identifiers, or GUIDs, as IDs.
Another solid solution would involve session validation of every request, along with proper access control.
Path Traversal Vulnerability
The idea behind path traversal is to navigate the directory tree of a filesystem without authorization.
This means that systems allowing users to access resources in the server file system are vulnerable.
This vulnerability is especially hazardous if the path string is accessible for modification and no validation exists.
To illustrate, look at the following scenario.
https://www.mywebsite.com/photos?file=user.png
In this scenario, an attacker could change user.png to ../../etc/passwd and access the application’s data.
To mitigate path traversal attacks you must implement proper validation of user input and restrict access to the server directory outside of the application.
Fortunately, responsibility for this usually lies within the server engineer. However, ensure that you implement robust and tested libraries if you enable functionalities that require accessing and modifying files in the server, like file uploads.
File Permission Vulnerability
File permission vulnerabilities relate to the server file system.
Applications contain many configuration files and resources that should not be modifiable and, in most cases, are not readable or executable for users. However, without proper configuration policies, an attacker can target these files and take over an entire platform.
To illustrate this, here’s an example of an attempt to access a file that should be unreadable.
https://www.mywebsite.com/photos?file=../../angular.json
Addressing file permission vulnerabilities requires extensive knowledge of server configuration and maintenance. So we advise that you consult with server engineers and avoid touching anything. Unless you absolutely need to tinker with the server permissions to add features related to file manipulation, leave this to the server engineers.
Client Caching Vulnerability
Now, it’s very likely that some of your clients share computers with other users. Unfortunately, that’s a circumstance that we, as developers, cannot control, but it enables vulnerabilities like client caching.
Client caching vulnerabilities are difficult to mitigate because they involve attackers taking advantage of a session credential, cached pages, or data stored in the browser of an authenticated client.
To exploit this kind of vulnerability, attackers need to have physical access to the victim's computer. Once they gain access, a sufficiently determined attacker can wreak havoc on user data.
For client caching, the most effective solution is simply not storing sensitive user information on the client. However, if you must, due to some business requirement, make sure to implement proper HTML meta tags and async validations to confirm authority on display.
Implementing Access Control
Many factors can make addressing access control vulnerabilities either very simple or incredibly challenging. Your system's architecture, the complexity of your platform, and the sensitivity of your data are but a few of them.
The first step to securing your system should always be to implement a proper authentication mechanism.
Implementing a solution like auth0 would get you most of the way there, in terms of security. For the purpose of this article, we only explore how to implement a basic auth0 login. However, you can also explore a solution like JWT if you want a bit more customization.
To start, run the following command to add auth0 to your Angular project.
ng add @auth0/auth0-angular
Now, go to the app.module.ts file inside the project src folder and import the module. You can specify the domain and client ID in this file.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
// Import the module from the SDK
import { AuthModule } from '@auth0/auth0-angular';
@NgModule({
declarations: [
AppComponent,
HomeComponent
],
imports: [
BrowserModule,
AppRoutingModule,
// Import the module into the application, with configuration
AuthModule.forRoot({
domain: 'YOUR_AUTH0_DOMAIN',
clientId: 'YOUR_AUTH0_CLIENT_ID',
}),
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Finally, go to the component where you want to add the login functionality and import the AuthService module.
import { Component } from '@angular/core';
// Import the AuthService type from the SDK
import { AuthService } from '@auth0/auth0-angular';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
title = 'My App';
// Inject the authentication service into your component through the constructor
constructor(public auth: AuthService) {}
loginWithRedirect(): void {
// Call this to redirect the user to the login page
this.auth.loginWithRedirect();
}
}
Now, all you need to do is set the proper domain and client ID, add a button to display the login, and voila, you have a login feature with an authentication mechanism.
Of course, there are many more tweaks needed to complete the implementation, but for that, we will guide you to auth0 wiki page, which has an extensive guide on how to implement their solution correctly.
Conclusion
Now that you understand what broken access control is and how you can mitigate it's impact through a combination of proper authentication mechanisms, proper system architecture implementation, and input validation, your systems stand a better chance against malicious actors lurking on the web.
There are as many different approaches to mitigate vulnerabilities in access control as there are vulnerabilities. What's more, every day, new threats appear on the web, and any of them could be devastating to our platforms.
Unfortunately, achieving robust access control policies can be an overwhelming task. This reality is especially true for big and complex platforms with many services and fronts.
Nevertheless, we must do what we can to close as many gaps as possible.
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.