Best Practices for Building Secure APIs
API designers and developers generally understand the importance of adhering to design principles while implementing an interface. No one wants to design or implement a bad API!
Even so, it’s sometimes tempting to look for shortcuts to reach those aggressive sprint timelines, get to the finish line, and deploy an API. These shortcuts may pose a serious risk — unsecured APIs.
Developers should remember to wear the hat of an API hacker before deploying. If a developer neglects to identify the vulnerabilities in an API, the API could become an open gateway for malicious activity.
Identifying and solving API vulnerabilities
An API can work for or against its provider depending on how well the provider has understood and implemented its API users’ requirements. If a company builds an incredibly secure API, it might end up very hard to use. A fine balance needs to be struck between the purpose of an API and ease of consumption. In this post, we’ll explore some of the API vulnerabilities we’ve come across through our work as part of Google’s Apigee team, including how these vulnerabilities might have been prevented.
APIs are the gateways for enterprises to digitally connect with the world. Unfortunately, there are malicious users who aim to gain access to enterprises’ backend systems by injecting unintended commands or expressions to drop, delete, update, and even create arbitrary data available to APIs.
In October 2014, for example, Drupal announced a SQL injection vulnerability that granted attackers access to databases, code, and file directories. The attack was so severe that attackers may have copied all data out of clients’ sites. There are many types of injection threats, but the most common are SQL Injection, RegEx Injection, and XML Injection. More than once, we have seen APIs go live without threat protection — it’s not uncommon.
APIs without authentication
An API built without protection from malicious threats through authentication represents an API design failure that can threaten an organization’s databases. Ignoring proper authentication — even if transport layer encryption (TLS) is used — can cause problems. With a valid mobile number in an API request, for instance, any person could get personal email addresses and device identification data. Industry-standard strong authentication and authorization mechanisms like OAuth/OpenID Connect, in conjunction with TLS, are therefore critical.
Sensitive data in the open
Normally, operations teams and other internal teams have access to trace tools for debugging issues, which may provide a clear view of API payload information. Ideally, PCI cardholder data (CHD) and Personal Health data (PHI) is encrypted from the point where data is captured all the way to where data is consumed, though this is not always the case.
With growing concerns about API security , encryption of sensitive and confidential data needs to be a top priority. For example, in June 2016, an http proxy vulnerability was disclosed that provided multiple ways for attackers to proxy the outgoing request to a server of choice, capture sensitive information from the request, and gain intelligence about internal data. Beyond using TLS, it’s important for API traffic to be protected by encrypting sensitive data, implementing data masking for trace/logging, and using tokenization for card information.
A major potential concern for enterprise architects is the so-called “transaction replay.” APIs that are open to the public face the challenge of figuring out whether to trust incoming requests. In many cases, even if an untrusted request is made and denied, the API may politely allow the — potentially malicious — user to try and try again.
Attackers leverage this misplaced trust by attempting to playback or replay a legitimate user request (in some cases using brute force techniques) until they are successful. In 2016, hackers got into Github accounts via a playback attack by reusing email addresses and passwords from other online services that had been compromised and trying them on Github accounts.
Countermeasures include rate-limiting policies to throttle requests, the use of sophisticated tools like Apigee Sense to analyze API request traffic, and identification of patterns that represent unwanted bot requests. Additional security measures to stymie replay attacks include:
- HMAC, which incorporates timestamps to limit the validity of the transaction to a defined time period
- two-factor authentication
- enabling a short-lived access token by using OAuth
Unexpected surges in API usage
It’s always tricky to estimate the usage of an API. A good example is the app that briefly brought down the National Weather Service API. This particular API didn’t have any kind of traffic surge prevention or throttling mechanism, so the unexpected surge in traffic directly hit the backend.
A good practice is to enforce an arrest in spike traffic or a per-app usage quota, so that the backend won’t be impacted. This can be easily rolled out with the help of a sophisticated API management platform with policies like quota and spike arrest.
Keys in URI
For some use cases, implementing API keys for authentication and authorization is good enough. However, sending the key as part of the Uniform Resource Identifier (URI) can lead to the key being compromised. As explained in IETF RFC 6819, because URI details can appear in browser or system logs, another user might be able to view the URIs from the browser history, which makes API keys, passwords, and sensitive date in API URIs easily accessible.
It’s safer to send API keys is in the message authorization header, which is not logged by network elements. As a rule of thumb, the use of the HTTP POST method with payload carrying sensitive information is recommended.
Many API developers become comfortable using 200 for all success requests, 404 for all failures, 500 for some internal server errors, and, in some extreme cases, 200 with a failure message in the body, on top of a detailed stack trace. A stack trace can potentially become an information leak to a malicious user when it reveals underlying design or architecture implementations in the form of package names, class names, framework names, versions, server names, and SQL queries.
Attackers can exploit this information by submitting crafted URL requests, as explained in this Cisco example. It’s a good practice to return a “balanced” error object, with the right HTTP status code, with minimum required error message(s) and “no stack trace” during error conditions. This will improve error handling and protect API implementation details from an attacker. The API gateway can be used to transform backend error messages into standardized messages so that all error messages look similar; this also eliminates exposing the backend code structure.
Keep APIs safe
As we have reviewed in this article, many potential threats can be avoided by putting some thought into API design and establishing governance policies that can be applied across the enterprise. It is important to guard APIs against malicious message content by accessing and masking sensitive encrypted data at runtime and protecting backend services against direct access. An API security mistake can have significant consequences — but with the right forethought and management, businesses can make themselves much safer.
This post originally appeared in Medium.