2. • API1:2023 – Broken Object Level Authorization
• API2:2023 – Broken Authentication
Two with one Scheme
3. • Incorrect implementation of authentication
• Allows attackers to compromise authentication tokens
• Paves the way for user impersonation
Broken Authentication
15. • Unauthorized access to objects
• Failures in access control mechanisms
Broken Object Level Authorization
16. • Unauthorized access to objects
• Failures in access control mechanisms
• Data disclosure, loss, manipulation
• Account takeover
Broken Object Level Authorization
17. • Use random, unpredictable values for (object) identifiers
• Implement authorization based on policies
• Validate permissions on every request
• Test authorization mechanisms
Prevent Broken Object Level Authorization
18. • Principle of Least Privilege
• Deny by Default
• Attribute-Based Access Control
Authorization Cheat Sheet
22. • Validate permissions on every request
• Implement attribute-based access control
Prevent Broken Object Authorization
23. • Authenticate all requests
• Validate permissions on every request
• Implement secure authentication
• Implement attribute-based access control
Addressing Top API Security Risks
24. • Delegate access with access tokens
• API Gateway for coarse grained access control
• Attribute-based access control with Claims
OAuth 2.0 to Mitigate Risks
Editor's Notes
Hello!
tired after long day => bedtime story: The Brave Little Tailor
Tailor kills seven flies with one blow of his hand.
Belt reading “SEVEN at ONE BOW”
=> everybody believes he is talking about killing seven men.
Defeats giants, unicorn and boar.
Becomes king.
Judith Kahrer, Product Marketing Engineer at Curity
Instead of killing seven with one blow, I am settled for addressing two API security risks with one scheme. In this talk, I show how to use OAuth to address the top of the top API Security Risks by OWASP. Number 1: Broken Object Level Authorization, and number two: Broken Authentication.
Broken authentication occurs when authentication is not implemented correctly. Authentication is the process of verifying if somebody is who they claim to be. If you mess up with authentication or session management, you won’t be able to know for sure who is who. You will eventually believe that the tailor is indeed a dangerous man because he looks like one.
When you break authentication and an attacker manages to compromise authentication tokens, temporarily or permanently, they can impersonate users. If an attacker manages to take over a high-privileged account, the potential impact is great and damage severe. Attackers may extend their exploit to other parts of the API.
What should you do instead?
First of all, do authenticate - always. Authenticate not only at the perimeter but also when communicating with other APIs inside the network. Base your solutions on standards, implement multi-factor authentication and protect the authentication process from brute-force attacks.
How does OAuth fit into the picture?
OAuth is a standard but OAuth is not authentication.
OAuth is about delegation.
However, delegation is exactly what you want for your APIs. Delegation means, that instead of authenticating and authorizing the user directly, access gets delegated.
Briefly, OAuth works like this: The client - that is the software that interacts with your API - gets a grant from the user. The client uses this grant to fetch an access token from the authorization server. This access token represents the delegated access from the user to some resources at the API. The client can now use this access token to call APIs.
When looking closer to the implementation of this abstract flow, you can see that the client does not collect the grant from the user directly but instead retrieves it via the authorization server.
So, in practice the story goes like this:
The client asks the user “Please seek the authorization server to provide me with the grant”.
The user goes to the authorization server and tells it: “I want you to deliver a message to the client with my grant.”
The authorization server answers: “Sure, but you have to solve this quest first to prove that you are worthy”.
Well, the last part of the story, is artistic freedom. What usually happens is that the authorization server challenges the user to authenticate.
Since the authorization server is a specialised component it can offer all sorts of authentication methods: Username and password, federated protocols like SAML and OpenID, passwordless techniques like WebAuthn and it can combine multiple. It can adapt the authentication process to the context. It can, for example, only enforce multiple factors when it considers it suitable. It can protect authentication with anti-brute force mechanisms like account lockout or cool downs. It can offer secure processes to recover passwords and accounts. In other words, the authorization server can offer secure authentication and account management.
If we now recall how to prevent broken authentication, you may realise that we can check three of them
- three at one blow!
What remains on the list is the requirement to authenticate all requests. And this is where the access token comes in. To simplify things even further for APIs, you can utilize an API gateway to enforce zero-trust.
Before any request hits your API services, the API gateway can ensure that all requests include a valid access token and perform coarse grained access control. The API gateway can also ensure that - no matter the structure of the incoming token - it always serves a JWT to APIs.
Then, the only thing your API has to focus on is to validate the access token properly and use it for authorization decisions to avoid Broken Object Level Authorization.
JWT validation includes, checking the validity time of the JWT. Is it issued by a trusted issuer? Is it intended for this API, does it include this API as an audience? Does it have a valid signature? When validating signatures, make sure to define a list of approved algorithms. Do not solely depend on the information provided in the JWTs. JWT header fields are unprotected and an attacker may trick the JWT validation algorithm to accept an invalid signature by manipulating header fields. Therefore, use asymmetric and hardcoded algorithms.
What may sound like quite some burden can be implemented with simple code as shown by the following pseudo code example.
Just define the validation options, that is the expected values for common claims like signature algorithm, issuer, audience or scope. Assuming you have the token and signature verification key ready, just call the verification function with the options.
Since OAuth is a standard and since JWTs are the de-facto standard for access tokens, there are plenty of libraries for various programming languages out there that support JWT validation.
After JWT validation, it's time to enforce authorization rules.
Broken Object Level Authorization occurs when users gain unauthorised access to objects. It can be the result of attackers manipulating object IDs that are sent with the request. The object ID may, for example, be part of the URL.
Unauthorized access means that there are failures in access control mechanisms which can lead to data disclosure, data loss, manipulation of data, or, in worst case, result in account take over. Trust me, you want to avoid all of it.
data disclosure, data loss, manipulation of data, or, in worst case, result in account take over. Trust me, you want to avoid all of it.
What should you do to prevent broken object level authorization?
OWASP recommends to use random, unpredictable values for object identifiers. Well, this recommendation only makes it harder to guess the value but randomising values doesn’t solve the underlying problem.
To actually prevent unauthorised access, define access policies and base authorization implementations on those policies. Validate the permissions on every request - wait! That sounds similar to what we have just heard in regard to authentication. Right. So, you need to authenticate AND authorize with every request. And, you should test the authorization mechanisms for different scenarios. Do not deploy anything that does not pass the tests - but I think that is almost self-evident to point out.
While the authorization server takes care of the authentication part, it is the API’s responsibility to validate the access token, the JWT on every request.
Then, after the basic validation you get into the details of the authorization policy. When implementing authorization keep the following cheat sheet in mind: Use the principle of least privilege. Users should only be granted enough permissions for the current context but not more. Deny by default. If you are not sure, be on the safe side and deny access. Implement attribute based access control. For the latter access tokens are a very suitable tool. You can implement attribute based access control with the help of access tokens.
An access token contains, standard claims like a subject, a scope or audience claim as discussed earlier. But it can also contain custom claims like the customer ID as shown in this example. Since the access token is signed, it is integrity protected, meaning you can trust that the claims in the access token are correct and have not been changed.
Use scopes for coarse grained access control. For example, to access the order API, you can define that the access token needs to include a scope with the value order read or order write. An access token with a scope order read is then accepted for a GET request on the order endpoint but insufficient for other endpoints or APIs, or even for requests using other HTTP verbs than GET on the order endpoint.
Additional claims like the customer ID can then be used for fine grained access control. For example, you can check if the referred customer has access to the given object. You can look up the customer and you can look up the object. You can check if and how they are related. Is this customer allowed to view the given order?
With claims in the access token you can implement attribute based access control and prevent broken object level authorization.
And because JWTs are self contained, the solution scales easily.
To prevent broken object level authorization, use OAuth to validate permissions on every request – e.g. perform coarse grained access control at the API Gateway. Implement attribute-based access control with help of the access token.
Once again, how do you mitigate the most critical API security risks?
You authenticate and authorize every request.
You use secure authentication methods. On a personal note, try to get rid of passwords.
You implement attribute based access control.
What do you need?
OAuth!
Because with OAuth you can outsource authentication and delegate access using access tokens.
You can call an API Gateway for assistance to enforce zero-trust and offload APIs.
You can implement attribute based access control using the claims in access tokens.
With OAuth you can mitigate two risks with one blow and open the chamber of opportunities ! Thank you.