This post is the start of a series about the 2019 version of OWASP API Security Top 10. My goal here is to learn more as I try to put the content I read into different words, and in this first post, we’re gonna be talking about Broken Object Level Authorization.
Very commonly, APIs use object identifiers (IDs) as a reference to which object will be the target for the action of a specific endpoint. Take this HTTP request below as an example:
GET /v2/users/1337 HTTP/2
Apparently, it picks up the value
1337 as the user identifier, and returns the following content:
HTTP/2 200 OK
Notice that this response includes a field called
super_secret_data. Judging by its name, we can assume that it contains data which should not be publicly visible. Let’s also assume, for the sake of didactics, that only the user
leet itself should be capable of get data from this endpoint while referencing to the user_id
So…given this endpoint, how do we grant that only
leet will be able to get data from
/v2/users/1337, and other users not?
Well, some may think that:
We just need to verify, before any operation, if the user who’s asking for an action is really supposed to be doing it.
And also, sometimes:
We could, whenever it’s possible, avoid the use of object identifiers on requests, so we rely less on user input.
Both thoughts are simple, and both really help. But if it’s so easy to avoid and fix, why does it get the TOP 1? Why is Broken Object Level Authorization the most common flaw we can find on APIs?
At the present moment, if we consider the most common tools that are used to construct APIs, there is no effective way to automatically handle access control limiting. It’s something that has to be done by the developers, endpoint by endpoint, and human beings are terrible when it comes to repetitive tasks, so they will for sure forget to add this extra verification eventually.
It gets worse when we’re talking about an API with countless endpoints, or an API that has to be maintained in different versions. Let’s get back to our example request:
GET /v2/users/1337 HTTP/2
In this new scenario, we did secure this endpoint by verifying if the session really belongs to the user with ID
1337. Now, our application is 100% secure, right? 💪
Not necessarily, because maybe if an user change part of the path from
v1, our Broken Object Level Authorization will still be there. Also, if users change the HTTP method from
PUT, maybe they’ll be able to update
leet‘s data as they want.
That’s why it takes so much effort to prevent API1:2019, and that’s the reason why it’s so common. Hope this post was somehow useful 🤗