Why REST API Security?
Software industry has been undergoing change at a rapid pace for quite some time now and so are the ways to design, develop, deploy and support software applications.
From large mainframe systems to microservice architectures, the industry sure has travelled a long journey (or rather still continues to do so). And in the process, software design and architecture has also changed from standalone, resource-heavy applications to service oriented design and distribution of these applications. More and more applications are now designed (and quite a few existing ones are being migrated) to provide their business services and data via APIs to end users and other applications for consumption.
However, these changing industry trends have also seen a massive leap in the area of data, information and service security. On one hand, as more and more sensitive data is getting digitized and stored on virtual platforms with enhanced security mechanisms, malwares too on the other hand, are getting smarter and finding new innovative ways of breaching these mechanisms to achieve their goals. And while they continue to outrun each other in a cat and mouse kind of scenario, our role as designers, testers and maintainers of software requires us to know and understand much more about securing our systems than just dealing with business logic and data.
Thus for any software system providing its services and data from any platform, Service APIs happen to be the first point-of-contact and thus, the first in line of fire from these malwares. REST APIs (or most of it, rather) are HTTP based, so it helps in ease of development for the same. However, this very aspect can also bring down the downfall of your application since hackers and malwares also have easy access to your application data via these APIs. Thus, understanding the techniques of securing these APIs has become a no-brainer expectation from designers and testers alike. And as more and more engineering teams are opting for RESTful architectural style as compared to SOAP APIs (for reasons beyond the scope of this article), I will discuss some of the techniques that we can apply to secure these REST API services from external threats. Note that the idea here is to eventually make things as difficult as possible for these malwares and hackers to make the breach, as it is probably impossible to eliminate the threat completely.
Calsoft Whitepaper: Storage Performance Testing Guidelines
What type of vulnerabilities a typical REST API may encounter?
Now that we all agree (hopefully) on why it is imperative to secure our REST APIs, it is equally critical to understand the various kinds of threats a typical REST API can encounter. Following are some of the key threats your APIs can encounter:
- Weak authentication and authorization techniques
- Using customized algorithms and tools for user verification instead of using industry standard tools and techniques
- Man-in-the-middle attacks
- SQL Injection attacks
- Invalid XML or incorrect JSON data
- Exposing data and API design via exceptions
- Cross-site Request ForgeryKeeping this scope in mind, let us look at the best practices on how we can mitigate these risks.
Since REST architectural style does not follow any specific single standard for its design (so far), neither can the security of REST APIs follow a pre-defined set of rules nor best practices. Note that some of the guidelines below can be directly related to decisions advocated by trusted security groups like OWASP, while others have been formed based on my own experiences while developing these APIs for some of my past projects and my discussions with a few like-minded people. And while I believe that none of these rules can be ignored, it should still be seen as work-in-progress for securing your application APIs and the data, these APIs expose. So without further ado, let us look at the best practices categorically:
Authentication and Authorization
Authentication is an identity process of confirming whether a user is the one he/she is claiming to be. Authorization, basically defines rules on what actions a particular user can do and what data he/she is given access to for reading and modifications.
While the two concepts can be thought of independent of each other, however they should be treated as a single mechanism of user verification when designing a robust REST API. Also, it is imperative that this verification happens via HTTPS protocol and the credential information travels in an encrypted form over the network. Overall, following can be thought of as some guiding rules for achieving this:
- Always, always – use secure authentication protocol like HTTPS for sending credentials over network.
- Never ever pass credential information in URL itself. It should rather be sent in HTTP request body so that there are lesser chances of it getting exposed directly to hackers.
- Always hash the password (with random ‘salt’ value) or any sensitive credential information at the client side itself. The server will always compare hash values of passwords rather than clear text for validation. Random salt will ensure unique value sent over the network which will be difficult for the hackers to guess using brute force or tools like rainbow tables.
- Always use a strong encryption algorithms like SHA-1 or SHA-2 series for hashing.
- Preferably use session based authentication, either by generating time-based session token or by using an API key (of course, as a POST body argument).
- Do not, I repeat – do not log passwords values in log files generated by REST APIs. That could result in a serious security breach.
- Use OAuth 1.0 or OAuth 2.0 for user authorization, instead of HTTP Basic API Authentication. OAuth 1.0 is considered more secure but complex to implement and less flexible in use, whereas OAuth 2.0 is considered less secure (since it uses SSL instead of signatures) but easy to implement and more flexible in use. Remember, OAuth is primarily an authorization protocol although it can be extended for authentication.
- Use Status code appropriately. HTTP 401 ‘Unauthorized’ is really for failed authentication while HTTP 403 ‘Forbidden’ is inform unauthorized access.
- Exception messages should be as generic as possible. Instead of saying ‘incorrect password’, you can reply back saying ‘invalid username or password’ so that we don’t unknowingly inform user that username was indeed correct and only password was incorrect.
This is a no-brainer really. However, the reason I have given it a separate section is because sometimes, how lightly it is taken by designers to validate inputs received by the APIs assuming that they have arrived certainly, from a legitimate user or client.Since REST usually deals with CRUD operations (Create, Read, Update and Delete), it uses HTTP methods (GET, POST, PUT, DELETE etc.) for implementing the same. These methods can send input data via URL, query string, HTTP Headers, cookies form fields or hidden fields. So to dissuade attackers from tampering with all these input sources, you can follow these best practices:
- Every API should be validated for its input content.
- Apply validations based on business logic, mandatory and optional values, null values, expected data types (especially for complex objects), relevance of the input as against the API inter-relation of data as and when applicable and number of validation failures permitted per client.
- Use a secure parser for parsing XML/JSON inputs.
- Give special attention to special characters and use proper encoding techniques if your API inputs are i18n-enabled.
- Use ‘Content-Type’ HTTP header to cross check whether input data received is of the same type as the header claims it to be.
- Use parameterized query APIs to avoid SQL injection attacks.
- If using cookies, make them secure by using ‘secure’ and ‘httpOnly’ flags.
The basic rule here is – try to keep your APIs as stateless as possible, no client state should be maintained on the server. So for every API call made by client, it will have to include all necessary information for the server to validate and fulfill that request. Using session based authentication could be one of the more popular techniques to achieve this.This also gives an advantage when we need to migrate the application to follow a distributed architecture. Stateless applications can easily be distributed across multiple servers and load balancers to serve more users that is possible on a single system.And when it comes to sharing the resource state from server to the client, only share the bare minimum details with hyperlinks to access next set of details, if need be. That way, you can limit the amount of data that needs to be transferred from the API to the client.
Pattern Based API Behavior
This best practice requires tracking the usage pattern of APIs by each user or client consuming the API. You should validate whether the business logic of your application allows for current API call, made by the user. While many consider this a secondary-level practice and may even think of skipping it (since it may require managing client state, which we said above that we should avoid), it actually can serve as a very important defense mechanism as it may deny the attacker from making any random API call to access a sensitive data when it was not expected of, whether it is from same session or multiple sessions.
So for e.g. if the API call sequence for an ecommerce application is about adding a certain category of articles, like electronics goods, in your shopping cart. And the application suddenly receives an API call for modifying the password for that user or for changing the credit card information for that user without receiving an API call to update user info, such an API call can be termed ass questionable.
The application in this case can ask a confirmation from the user whether he/she really intends to make such kind of change. Or it can also ask the user for its credentials again before attempting such an action.
So, while all the best practices above will help in creating a highly secure API design for your application, many engineers always come across this confusion as to whether they should use HTTPS for each and every API call, or whether it should be restricted to user verification stage only?
My suggestion would be that ideally using HTTPS for each and every API call would be the right way to go, although it may be seen as overhead at times. Nowadays, hardware costs for memory and CPU are way cheaper that they were around 10 years back. HTTPS back then was considered a heavy-duty protocol, to be used judiciously only. But with servers running on cheaper hardware and with more powerful but optimized feature set, the value of securing your sensitive data is way higher than the hardware resources your applications run on.
So, using HTTPS throughout for all your API calls should be the way to go. You can use HTTP-only design for doing prototyping and testing purpose only while designing your APIs.
In case you plan to use a particular REST API framework, do ensure that all of the above security guidelines are fulfilled by that framework and if not, whether it provides any mechanism to extend its feature set by adding a custom library which provides any of the missing feature from the above guidelines.
Thus so far, if you follow the above guidelines, you can be REST assured that your application services and data cannot be easily compromised and you ensure a robust, secured and consistent API experience to the consumers of your API. QA engineers can also use these guidelines to prepare their test plans and test cases to ensure that REST APIs for any application are robust enough with above security features.
Thank you for your time reading through this blog and happy API designing!!!