API5:2019 Broken Function Level Authorization
From the summary you might have been able to gather this vulnerability can be quite complex and varied. Humans are predictable in nature and they tend to follow several patterns when it comes to hosting endpoints, for example it usually occurs that higher privilege endpoints are hosted on the same relative path, which makes it easier for the users to guess these endpoints but that alone does not make them vulnerable. We have to be able to access to endpoints as a lower privileged users as well of course. This access can occur by executing the provided HTTP method (for example POST) but it can also occur on other methods that the developers left enabled (un)intentionally (for example DELETE). These issues are often made worse by how predictable the endpoints are (for example /books?id=0 might indicate the presence of an endpoint /books/all which may print out books the user should not be able to access.).
In our first example we will be looking at a target which contains two types of accounts: Franchise holder and a company looking to exploit the franchise. Both log into the same URL but the Franchise holder type of account is much more expensive. However by going to the account settings and saving, we notice a hidden parameter "Account type" and we change it from "exploitant" to "franchise_holder". This allows users to buy a lower priced type of account and change it to higher priced account type themselves later on.
Example:
POST /api/saveSettings.php
[
{
"Name": "677",
"...": "AAAAA...AAAA"
"AccountType":"exploitant"
}
]
We change this body to
POST /api/saveSettings.php
[
{
"Name": "677",
"...": "AAAAA...AAAA"
"AccountType":"franchise_holder"
}
]
and by sending this request, the users can upgrade their own accounts to a more expensive account type.
A second example we can add is where users try to view documents however they can only view their own. By exporting their own documents though, the user is presented a URL /api/documents/export. This URL does return the proper documents and only the only belonging to the user but by simply guessing, the user discovers a URL that returns all the documents on /api/documents/export/all.
GET /api/documents
Will return the following response
[
{
"id": "1",
"content": "AAAAA...AAAA"
"creationDate":"10-10-10"
},
{
"id": "4",
"content": "AAAAA...AAAA"
"creationDate":"10-10-10"
}
]
Since this user can only see their own documents, they can only see those 2, however if they export the documents, the user notices they can change the path and export all the documents.
GET /api/documents/export/
will return the same as before, however the following:
GET /api/documents/export/all
exports all the documents.
It's always better to seperate the authentication and authorization module from the main code and make it easy to implement where needed. By default all access should be denied to make it safer, we can also work on blocking the traffic we do not want but this would make it easier to miss certain paths of attack.
Besides this we should conduct regular and thorough testing and analysis of the autorization module while we keep the logic of the application and the different user levels in mind.
To make things extra secure we can implement a master admin class that implements the main authorization modules as mentioned above. We can use this master admin module to inherent from all other administrative functions to limit the chance of administrative functions being executed by lower priviledge users.
Lastely we always need to keep 2 factors in mind:
We have to make sure that with those two factors checked, only administrators can access administrative functions.
To test for this, it is wise to at least partially rely on test automation due to the predictable nature of APIs and how they are structured. A potential test could be to run the OPTIONS method on every API endpoint and to make sure those API endpoints do not allow for any unexpected method. We can also automate the checks of user roles and groups, this requires a proper definition of all the user roles and groups with their access levels.