Broken access control
Making sure we authenticate and authorize correctly
Select your ecosystem
What is broken access control?
Access control refers to the permissions structure that should be defined by the application. For example, your application may have separate roles for regular users and administrators. Regular users should not be able to obtain priviledged access, but administrators should!
When the access control of an application is broken, a regular user may be able to access functionality that is meant to be reserved for administrators, or perhaps they can access data that does not belong to them.
About this lesson
In this lesson, you will learn about how broken access control vulnerabilities work and how to protect your applications against them. We will step into the shoes of a devious college student who exploits one of their university web applications to award themselves an unearned high distinction.
Authorization vs. authentication
Before we start, there's one important distinction to make!
"Authorization" and "authentication" are similar words that are often confused. It is important to know the difference between them. Authentication is the process of determining who someone is, while authorization is the process of determining what that person is allowed to do, or what they have access to.
When people talk about broken access control, they are referring to authorization, not authentication.
In our example, your name is Ezra. You're a particularly intelligent college student with a penchant for hacking, and a willingness to break the law for personal gain 😈. This semester, you really need to pass a Statistics class in order to graduate with a Computer Science degree. The thing is, your exam was today, and you slept through it because you were up late hacking last night. You could pay thousands of dollars and wait six months to retake the exam or you could put those hacking skills to work? It wouldn't hurt to just take a look...
You sign into the web application that allows you to check your grades, https://grades.patch.edu
. You passed every subject except Statistics. It currently shows an F for Fail.
Insecure Direct Object Reference (IDOR) vulnerabilities
If you're really observant, you may have noticed that the GET
/grades route also does not contain any access control restrictions. This means that an attacker could easily view the grades of other students by guessing a valid student ID instead of their own. For example, your student ID is 20223948, so sending this request would return your grade:
GET /grades?studentid=20223948&subjectid=1293 HTTP/2Host: api.grades.example.com
But if we simply change the student ID to 20223949, then we would return the grade of the student with the id 20223949! With a few minutes of coding, this process could be automated to download the grades of thousands of students, for example:
What just happened?
What you just witnessed was a classic instance of broken access control. Of course, a student should not be able to edit their own grades, but the API did not properly enforce role-based restrictions on the server-side. While students do not see any method of updating their own grades within the UI of the application, they are still able to send specially crafted raw HTTP requests directly to the API to make these changes.
Note: For the sake of simplicity, we skip any error checking in the example code.
The underlying code might look something like this:
As you can see, the updateGrade()
function contains no access control restrictions. As a result, anyone who can send requests to the web server is able to update grades.
In recent years, application frameworks have come a long way. Unfortunately, frameworks do not yet have the capability of automatically implementing permissions structures. Permissions structures still need to be implemented by the developer, because every application has specific, custom requirements.
In most cases, the reason that access control is broken is simply because it has not been implemented, in which case, of course, the mitigation is to implement it! If we were to implement some rudimentary access control on the GET
endpoint in the code above, it might look something like this:
In this case, the getCurrentUser()
function would return the details of the currently authenticated user, based on their API key. If the user's ID is not the same as the ID they are requesting, then it will return an "Access Denied" message instead of the grade details.
The PATCH
endpoint presents a different problem, because we want teachers to be able to upgrade the grades, but not students. In this instance, we need to implement role-based permissions. A rudimentary example may look like this:
The code above will return an "Access Denied" message unless the user's role is set to "teacher".
Test your knowledge!
Keep Learning
- There are some excellent learnings on the OWASP Authorization cheatsheet
- See some statistics on Broken Access Control vulnerabilities on the OWASP top 10 page
- Role and Attribute based Access Control for Node.js