
In this article I will try to give the basic explanation of Insecure Direct Object Reference (IDOR) as one of the most common types of broken access control vulnerability.
This can occur in the application where user-supplied input is used to access objects directly.
For example, this attack can occur when the server fails to validate an incoming HTTP request to access data/object. If the application cannot authenticate the user, some of the underlying object details will be public, and the attacker could easily see them. In that scenario, attackers can use revealed information such as the “id” parameter to continue the attack. In many web applications that use IDs to identify users, the admin will likely be equal to 0 or 1. A successful attack would compromise users’ sensitive information such as personal data (for example, financial details).
*Note: This attack is most seen when the database uses auto-incremental IDs, which are used to access the object via URL. There is one great article if you want to learn how to create autoincrement ID in a database.
This is one example how what it looks like when you are accessing an object by ID in URL:
https://test.com/user/id/1234
Application security gaps:
- not sufficient authorization checks when accessing internal data
- API reveals a direct reference to data or some logic that can contain helpful information for the successful attack
- not appropriate user-supplied input validation
- when authentication is just implemented on a front-end side of the application
All these gaps can impact unauthorized information disclosure, modification of data, destruction, and performing a function outside the user’s limits.
Types of IDOR Attacks explained on this site:
- Body Manipulation (modifying the value of checkboxes, API endpoints, radio buttons, and input form fields)
- URL Tampering Attacks (attacker alters HTTP request parameters by modifying URL parameters on the client-side: GET and POST)
- JSON ID Manipulation (attacker may intercept JSON data sent between APIs, servers, and the web application to gain unauthorized access to application configuration and data)
- Mass Assignment (attackers manipulate a record pattern to modify large data sets that they are not authorized to access)
Links for ID decoding
Keep in mind that when developing, if you are just going to encode an id which is a number that attackers can easily decode. Also, there is a site https://crackstation.net which uses massive pre-computed lookup tables to crack password hashes. So first, when you are deciding on which logic you are going to use for IDs, test them on these sites.
- https://gchq.github.io/CyberChef/
- https://www.base64encode.org/
- https://crackstation.net
- https://hashes.com/en/decrypt/hash
- https://www.dcode.fr/ (this site is in French, but you can translate it. If you are using Chrome; right-click on the site and press “Translate to English”)
Prevention steps:
- Implement access control policies to prevent user access outside of their intended permissions
- Try to hash all sensitive data, such as functions and values
- Try to use Globally Unique Identifiers (GUIDs) to identify reference objects, not just integers as id. GUID is a 128-bit text string that represents an identification. If you want to familiarize yourself more with GUID, you can check out this helpful site.
- Apply authentication on the front end as well as in the back end. The best practice is to apply it on both sides, but if you need to choose, back end is the crucial side because it has direct access to the database
- Use this approach for checking our permissions: intercept request when it is trying to access an object, check if the user has permission to view that type of resource or that resource
Use Default-Deny Approach
One of the approaches you can use is Default-Deny.
What does it mean?
This approach first denies all access to the resource. After that, you should explicitly define the permissions and the relationships between the role and the requested object (resource).
Any request for a resource that is not explicitly allowed is automatically denied.
The alternative would be the allowed-first approach. In this case, you specify which permissions are denied, and all else will pass to the object.
How to choose which approach to use?
The best practice when developing an application is to implement permissions before the application is in the production stage. In that time, you can see what it would be easier, depending on the application’s logic, to use deny first or allow first approach!
Use Route-Guards to secure Angular pages
You can implement route guards to allow, deny or redirect to another page view.
Route guards are used to restricting the manipulation of URLs. Imagine you have one application, and only the admin can see the users page so he can add or remove users:
https://test.com/users
If you implement a route guard in the application, you would be able to restrict who can enter the requested page.
I will show you what it looks like when the application uses Route guards. I will create one class that will present Role Guard, which implements the CanActivate interface from “@angular/router,” so we can use its canActivate method.
import { ActivatedRouteSnapshot, CanActivate, Router } from "@angular/router";
import { Injectable } from "@angular/core";
import { LocalStorageManager } from "app/common/services/local-storage.manager";
import { Observable } from "rxjs";
@Injectable()
export class RoleGuard implements CanActivate {
constructor(
private route: Router,
private _localStorage: LocalStorageManager
) {}
public canActivate(
route: ActivatedRouteSnapshot
): Observable<boolean> | boolean {
return this.isRoleAssigned(route.data.roles);
}
private isRoleAssigned(roles: string[]): boolean {
let assignedRoles = this._localStorage.retrieveObject(
this._localStorage.roles
);
if (assignedRoles.roles.filter((role) => roles.includes(role)).length > 0) {
return true;
} else {
this.route.navigateByUrl("home");
return false;
}
}
}
In this example, all roles are already stored in local storage, so we don’t call API and create an HTTP request each time when we need to get the roles.
Method isRoleAssigned is used to check if the user has a role that is the same as needed for accessing this page. If the user has the required role, then they can access the page and, in this case, it will return “true” if they don’t have the application, it will redirect tehm to the “home” page, and the method will return false.
We will get the required roles from the route.data.roles. You can see these roles in the picture below in app.routing.ts => data => roles.
The next step of the implementation is to import this class into the app module as providers:
@NgModule({
imports: […],
declarations: […],
providers: [ …, RoleGuard],
… })The most important place where we will connect RouteGuard with the page (component) is in app.routing.ts
export const routes: Routes = [
{
path: " home",
component: HomeComponent,
data: { title: "Home" },
},
{
path: "users",
component: UserComponent,
data: { title: Users, roles: ["Administrator"] },
canActivate: [AuthGuard, RoleGuard]
}
]You can see in this picture that we don’t have any restrictions for the home page, but for the user page, we have added RoleGuard, and we will pass that only the Administrator can access this page.
This is some very simple code, but we have restricted the page access, so the attacker cannot manipulate and access pages from the URL! You can check out the site if you want to learn how to create AuthGuardService.
Useful links:
In one OWASP presentation there are some useful links for IDOR explanation and examples, if you want to check them out:
- https://codeburst.io/hunting-insecure-direct-object-reference-vulnerabilities-for-fun-and-profit-part-1-f338c6a52782
- https://www.gracefulsecurity.com/idor-insecure-direct-object-reference/
- https://medium.com/@woj_ciech/explaining-idor-in-almost-real-life-scenario-in-bug-bounty-program-c214008f8378
- https://blog.detectify.com/2016/05/25/owasp-top-10-insecure-direct-object-reference-4/
Conclusion
I showed some basic mistakes made while developing and some prevention steps to avoid them.
In my opinion, the most essential part of application security is authentication. This logic must be implemented in the right way. Of course, that means it needs to be tested in detail because it is too late if broken authentication passes to the production stage.
In the end, secure code is the cheapest code!
#IDOR #route_guard #vicarius_blog
Cover photo by Towfiqu barbhuiya
About Version 2 Digital
Version 2 Digital is one of the most dynamic IT companies in Asia. The company distributes a wide range of IT products across various areas including cyber security, cloud, data protection, end points, infrastructures, system monitoring, storage, networking, business productivity and communication products.
Through an extensive network of channels, point of sales, resellers, and partnership companies, Version 2 offers quality products and services which are highly acclaimed in the market. Its customers cover a wide spectrum which include Global 1000 enterprises, regional listed companies, different vertical industries, public utilities, Government, a vast number of successful SMEs, and consumers in various Asian cities.
About VRX
VRX is a consolidated vulnerability management platform that protects assets in real time. Its rich, integrated features efficiently pinpoint and remediate the largest risks to your cyber infrastructure. Resolve the most pressing threats with efficient automation features and precise contextual analysis.

