Today, we’re going to dig into the most common methods of API authentication out there and discuss some of the security implications associated with each of them, from the perspective of a penetration tester. As Application Programming Interfaces (APIs) continue to become a more prevalent tool used in website architecture, the security associated with them continues to grow in importance and people may not be as familiar with them.
Authentication is probably a good starting point if you’re looking into the security implications and concerns surrounding APIs. At a high level, authentication is when you prove you are someone (identify yourself) that has been granted access to a particular resource. In the case of APIs, there are many different use cases that carry different requirements with them in regards to authentication.
For example, is this a public API that is intended to be released and used by anyone who wants to? Are we talking about a private API that is used by a single web application or a family of web applications within a company? Is it a licensed API that other business can buy access to? In all of these scenarios, there will probably be a different set of circumstances, business objectives, and limiting factors that will need to be considered when it comes to authentication.
Let’s look at some of the most common methods of API authentication and their implications.
Yes, this is always an option, and in certain cases may best fit your use case. But in the vast majority of API Penetration Tests we do, if there’s no kind of authentication whatsoever it’s very concerning. You should really only use no authentication if every bit of data within your API and all functions/processes are not sensitive and intended to be exposed to the entire Internet.
Even then, if you own the underlying server you should extremely thorough in your testing as there is no barrier to entry for attackers to poke and prod the API, significantly increasing the exposure. Couple this with the fact that the API definitions would need to be publicly documented so users know how to interact with it, also exposing those definitions to potential attackers, and you should be very wary of leaving an API with absolutely no authentication mechanism.
Slightly improving over absolutely no authentication we’ve got Basic Authentication. This authentication is not specific to APIs and you very well may have encountered this in other areas, as many legacy network devices used to authenticate this way. Basically (pun intended), this is just an HTTP header with a simple base64 encoding of the string “username:password” and sent in with a request.
This method is very quick and there’s no complex session tracking or handshakes associated. There are several security concerns with Basic Authentication, however. First, since the credentials are only base64 encoded and not hashed/encrypted, they are only protected by the transport security of the connection to the target API (TLS hopefully). But even with TLS wrapping the packets containing the encoded credentials, they could still be intercepted through man-in-the-middle attacks or downgrade attacks that open the traffic up to sniffing. Additionally, Basic Authentication has no concept of account lockouts in most cases unless that is a custom addition, so the credentials would be extremely susceptible to brute force and other types of password attacks anyway.
API keys were developed as an initial fix for the issues plaguing APIs leveraging no or Basic authentication methods of API authentication. An API key is just a uniquely generated identifier that is assigned to each application user, and they supply that key as a header to each of their requests to the API. The API has a tie to see that that key is assigned to Bob Dole and he is allowed to access the API, so the request is processed.
So again, we’ve got an authentication which is fast and simple. It even stops the brute forcing element of Basic Authentication (assuming the keys have sufficient entropy) and does require some kind of shared secret, unlike no authentication at all. You can probably see some of the security shortcomings at this point, though. Similar to the string passed with Basic Authentication, if any point in which the packet is transmitted is insecure and that information can be captured, an attacker can simply grab the key and replay it with their own requests. Additionally, these keys have to be rotated to reduce the time of exposure, which introduces additional overhead. Ultimately, using these keys as a shared secret isn’t a great solution as they could get cached in network devices/logs, exposed through cleartext communications, etc.
OAuth is “an open protocol to allow secure authorization in a simple and standard method from web, mobile, and desktop applications.” It’s kind of a hybrid authentication/authorization scheme all rolled into one, unlike the previous options we talked about which were focused on authentication only and would require an extra layer of authorization checks. OAuth is a powerful system because it allows a user to authenticate with traditional mechanisms (username/password + MFA hopefully) and receive an authentication token that is passed in with each request.
The token issued can be managed, revoked, etc. independently of the users actual credentials, making it much more secure due to the limited scope and validity. It can also be used to tie application authentication together more seamlessly in cases where there is a mobile app and web app that leverage the same API, for example. It significantly reduces the exposure of the tokens used as new ones are generated for the same user each time they authenticate and additional checks can be put in place to associate a token with a browser fingerprint, for example. It can be more complex to implement because it is obviously more full-featured than the other authentication methods out there.
So ultimately, among all these methods of API authentication, the one you use for an API will be heavily dependent on your business use case and your data sensitivity/threat model. But some authentication mechanisms are more secure than others and options like OAuth should get heavy consideration when you’re looking at securing an API. If you’re interested in what risks are associated with your APIs currently, feel free to reach out!