Introduction
API stands for application programming interface which basically means that we have an exposed interface that can be adressed programatically. As the internet becomes available in more and more locations around the world, the types of interfaces will become ever more prevalent. Securing an API can easily cost as much as the feature development itself and it can even cost more which is why are decided to write this article in the hopes of guiding you throughout this wild landscape and even though we are well aware that REST API's are not the only kind, they serve a specific purpose and we want to make sure the security risks are understood when implementing such a REST API.
What is a REST API
REST stands for Representational state transfer which means that it defines a programming architecture which uses the HTTP Methods. (GET/POST/DELETE/PATCH/...). Using these HTTP-method allows us to create our APIs independant of what host OS it will run on. The following poperties have to be fulfilled before we can speak of a RESTful API:
- Works on the CLIENT-SERVER architecture where the clients use HTTP calls to communicate with the APIs.
- RESTful APIs are stateless which means they do not account for already known information of the object that is being processed. These so called states will never be passed between requests
- A RESTful API has to allow for caching of often used resources
- RESTful APIs have a uniform way of communicating with other APIs
- The variables are URI based and have to be identified with the URI, for example /invoices/1/print
- They will contain Content-type headers describing the meta data of the API
Eight security principals of secure REST APIs
Securing these REST API endpoints is no easy feat and it will often require some custom solutions but we can define a general list of API design principles which will help keep your code more secure.
- Least Privilege: A system should be analysed very carefully and should only be passed rights to an application if those rights are absolutely needed. Permissions should be removed when they are no longer needed either.
- Fail-Safe Defaults: This means that a user should not have access to any resources by default (fail safe) and they should only be allowed to view a resources after receiving explicit permissions.
- Economy of Mechanism: The more complex a system and it's interfaces is, the more chances there are for something to go wrong and when it does go wrong, the chances are also bigger that the severity will be higher which is why we should strive to keep our complexity down as much as possible
- Complete Mediation: On every action that is executed by the system, it should verify whether or not the user is allowed to do that action using a list of user rights that's created on the spot and not using the cached data
- Open Design: While some companies might be convinced that keeping as much source code a secret is a good idea, you and I both know better. Having the guts to expose software that was written for internal usage up to bug bounties is a thing of beauty and any serious manager should consider it to be honest
- Separation of Privilege: specific users should never gain access to a specified object based on 1 critirium but ideally multiple selection criteria should be used to define 1 users access. This way we can have more fine grained control
- Least Common Mechanism: We have to think about sharing states between calls carefully as if we can corrupt the state of the object at any point, the flow that is predefined might no longer work as expected