...so there you are, building an API, and out of nowhere you had an epiphany that there is a security flaw in your user authorization flow, so you rush to fix it.
Wheew, that was close, right? 15min later, and that would be on production servers risking actual user data leaks
Then you start to worry about possible security flaws on your app, (and you definitely should be worried about that).
In 2022 we had some noticeable incidents on API security, one of them regarding Twitter, cybercriminals managed to sell user data for 5.4 million, exploiting an API vulnerability disclosed.
So if you don't want your, or any of your user's data leaked, you should keep an eye on that.
OWASP keeps track of the 10 most common and most used API exploitation methods https://owasp.org/www-project-api-security/.
And I wanted to talk a little about the three most common security threats.
This tutorial is not specific to any language or technology, the subject cited can be used in any language or technology that you can create APIs on
Broken Object Level Authorization
Object level authorization is an access control mechanism that validates that one user can only access objects they should have access to.
Broken Object Level Authorization vulnerabilities occur when there is no object-level authorization, and users can access resources that they shouldn't be allowed to.
Attack scenario:
- A blog website provides a listing page to all of a user's private blogs, that page only shows if the user is currently signed-in. An attacker identified a pattern inspecting the browser request, and sees that the private page has a pattern
/blogs/{userId}/private
, and if that website doesn't have object level authorization, all the attacker must do is to change the userId to someone else's ID and read all of their private data
How to avoid that.
Implement an authorization mechanism that focuses on user policies and hierarchy, there are a bunch of ways to make policy-based authorization, one solution that I like is to create an ACL (Access Control List) allowing access only to users with certain permissions and or roles
Use UUID
UUIDs are made of random (or not so random) characters, with numbers, letters, and dashes, made to be unpredictable, and unpredictability is always a plus in security
Middleware check
Check if the logged-in user has access to perform the changes to the database, that he is currently trying to
Testing
Write tests to your authorization mechanisms, and try to cover all of the possible authorization flows
Broken user authentication
It occurs when there are weaknesses in how an API authenticate its users, allowing attackers to make requests as if they were a legitimate user
Attack scenarios:
A user uses a public computer to access his account, and instead of clicking logout, he simply closes the tab, due to session timeouts not being set properly he would be still logged in after hours, and when an attacker would use this public computer the user's account would still be authenticated.
An attacker has a stolen list of a user's usernames and passwords from other websites, using an automated process the attacker uses every combination possible to fraudulently gain access to other accounts
An API is vulnerable to this type of attack if it:
- Permits credential stuffing (automated injection of stolen credentials to fraudulently gain access to user's accounts)
- Permits attackers to perform a brute force attack on the same user account, without presenting a captcha/account or lockout mechanism.
- Permits weak passwords.
- Sends sensitive authentication details, such as auth tokens and passwords in the URL.
- Doesn’t validate the authenticity of tokens.
- Accepts unsigned/weakly signed JWT tokens
- Uses plain text, non-encrypted, or weakly hashed passwords.
- Uses weak encryption keys.
How to prevent that?
Don't reinvent the wheel
Stick to what works, don't reinvent the wheel on authentication, and use trustworthy and standard methods.
MFA
Implement multi-factor authentication where possible.
Design flaws
Make sure you know all the possible flows to authenticate.
Anti-brute
Implement anti-brute force mechanisms to avoid credential stuffing
Excessive Data Exposure
Excessive data exposure is a vulnerability that consists in sending sensitive data to the client.
Attack scenario:
A social media app provides a listing page to see all posts on your feed, also providing a
moreInfo
button, where you can see specific details about the post, such as tags, etc.Checking the browser requests, an attacker sees that the endpoint
feed/posts/{postId}
, also returns sensitive data about the user who created the post, information such as email, name, and more.
How to avoid that:
Filter through backend
When filtering data, do it before sending it to the front-end, never rely on the front-end to filter data.
Is it necessary?
Make sure all of the data providing in the API response is necessary
Who is consuming it?
Ask yourself whenever returning data, who is the consumer of this?
Validate your schema
Implement a schema-based response validation mechanism, that defines and enforces data returned by all API methods
Final considerations.
Dealing with API security can be pretty annoying, you need to think of authentication flows, API input, API output, etc in a lot of different scenarios, but security is a must in a real word application.
There are a lot of ways you can make your API more secure, but remember to stick to the basics, using methods that are known to work, can save you from a lot of headaches in the future, for example, good and standard ways to secure your API, besides from the ones listed above:
- JWT (Authentication)
- Access Control
- OAuth
- Always check and validating your input and output
- Monitoring and logging
- Load balancer and rate limits for API
- And of course, the last one, encryption, to protect sensitive data
Thank you very much for reading here, I hope I've managed to help you in your quest of creating the most secure API ever.
Top comments (0)