APIs have become increasingly prevalent in the last few years as companies have begun to focus on digital transformation and migration to the cloud. APIs are a large part of what makes the cloud possible. They’re used to access and manage our cloud resources and connect microservices to build our applications. As developers grew to rely on these interfaces, attackers began to notice how they could be exploited to gain access to our most valuable data. APIs are becoming one of the most exploited attack vectors in application security, but there are measures that can be put in place to reduce your exposure to these types of attacks.
Use OAuth and OpenID Connect for Authentication and Authorization
Before an API processes a request, it should perform an authentication check to ensure that the entity making the call is really who they say they are. Traditionally there are a few ways this has been done with varying degrees of security. The simplest is HTTP basic authentication, in which a base64 encoded representation of the username and password is included in a header sent with every request. Basic authentication is usually not recommended as it requires the user to provide a password to the application, which you then need to worry about securing. Another method typically used is API keys. The application is given an API key, and that key is included in the request, allowing the API to recognize that it is the correct app making the request. This is limiting, however, because it identifies the application but not the user. It is also fairly easy for API keys to be leaked. The most popular, and most secure, method for authentication used today is OAuth with OpenID Connect.
OAuth is not actually an authentication mechanism, but an authorization framework. Here the resource owner, or the person whose data is being accessed, is redirected to an authorization server, a third-party trusted by both the resource owner and your API. That third party verifies the identity of the resource owner and asks them to grant the client, the application asking for the data, permission to access specific information. When the resource owner agrees to the scopes requested, the authorization server sends the resource owner back with an authorization code. The client then contacts the authorization server with the authorization code from the resource owner and their client ID and client secret, information that the app has been granted by the authorization server as a means to identify them and verify that the API is allowed to be asking for info. The authorization server then sends back an access token after verifying the data. The token has a defined expiration but can be used to send requests for the desired data. Essentially, OAuth has authorized the app to access the user’s data without the user providing their username and password directly to the application. Authorization has been granted, but authentication has not. OAuth just knows that a token was requested, it doesn’t know anything about the identity of the end user, which is where OpenID Connect comes in.
OpenID Connect provides the authentication piece, providing information about the resource owner back to the client. The workflow is similar to OAuth, but the client is also provided with an ID token in addition to the access token.
Using OAuth and OpenID Connect protects the API as it is only receiving tokens, not authorization information, and the user is protected from having to share their credentials with another site.
Don’t Provide Extra Information
“Don’t provide extra information” is a simple way to sum up several best practices for API security. First, you want to avoid excessive data exposure. Excessive data exposure, which is ranked third on OWASP’s list of top API risks, refers to when an API returns more information than is actually needed. Instead of filtering to only supply the pieces of information requested, it pulls the entire object from the database and sends all of the data, relying on client-side code to filter out what isn’t needed. This leaves the information unnecessarily vulnerable to man-in-the-middle attacks, identity fraud, data breaches, etc. Don’t leave filtering up to the client, but instead craft your APIs to limit what is returned. You should also ensure that all sensitive data being transferred between the user and the API server is encrypted using Transport Layer Security (TLS) protocol so that if information is leaked, it is less likely to be able to be used. so that if information is leaked it is less likely to be able to be used.
Another source of extra information is error messages, what is known as improper error handling. You want to provide enough information that the developer or end user can fix what is going wrong if they are a legitimate user, but you don’t want to provide extra information that could give an attacker clues as to how the application operates, which could be used to enable an attack.
Finally, take confidential information such as credentials or API keys out before making the API public. Don’t store your API key directly in your source code, and don’t leave your API keys unencrypted in a code repository.
Validate Inputs
Many common API vulnerabilities, such as SQL injections and buffer overflow, are made possible by a lack of validation for inputs. Setting validation policies is essential to limiting the likelihood of successful attacks. Setting validation policies is essential to limiting the likelihood of successful attacks.
- Validate content policy: Validates the size or content of the request against an API schema like JSON or XML. This validates the content, such as if all required properties are present, the types of properties, and the format of the properties.
- Validate parameters policy: Validates the header, query, or path parameters in requests against the API schema.
- Validate headers policies: Validates the response headers against the API schema.
- Validate status code policy: Validates the HTTP status codes in responses against the API schema. This helps protect against the aforementioned leaking of extra information in your error messages.
Implement Rate Limiting
Rate limiting is putting in place constraints to avoid unlimited use of your API. Without rate limiting, users can make as many requests to your API as they would like. This is a problem as it allows unlimited attempts for users who are attempting to brute force. It also allows for purposeful attempts to flood the server with requests, such as in a denial-of-service attack. Rate limiting can be deployed in a variety of ways, including limiting overall traffic from all users, limiting how much traffic can come from one user, or limiting how much traffic one user can send to a specific API. Rate limiting can also mean throttling as opposed to putting in place quotas, which instead of completely blocking traffic, just slows service to users making too many requests. To put rate limiting in place, you will need to determine a baseline of what a “normal” level of requests would be and put in place restrictions on traffic beyond those thresholds. To put rate limiting in place you will need to determine a baseline of what a “normal” level of requests would be and put in place restrictions on traffic beyond those thresholds.
Log Activity
Logging activity is essential for understanding what has gone wrong in the event of a successful attack. API logging will help you monitor for abnormal API usage, such as authorization and authentication failures or input validation failures. You should also integrate your API logging with your SIEM and other tools for monitoring and alerting.
Use an API Gateway, Service Mesh, and Firewall
Put in place tools that will help detect and block abnormal traffic. API gateways route API requests and help enforce security policies such as encryption, authentication and authorization, and rate limiting.
A service mesh is similar to an API gateway, but instead of routing external requests, it helps internal microservices communicate with one another. As it does this, it improves security by encrypting the data that is traveling between microservices (mutual TLS). It also helps implement policies of zero-trust by authenticating the microservice that a request is routed to as opposed to explicitly trusting it.
Finally, just because you have an API gateway doesn’t mean you don’t need a web application firewall. WAFs help protect your web-facing services, including APIs, from known attack patterns, abnormal requests, and bots.
Test Your APIs
Just like any other element of your application, APIs should be subject to security testing during the development process. APIs must be designed with not only functionality, but also security, in mind. Static Application Security Testing (SAST) can be applied to APIs to analyze the source code, however, these tools are not always designed to identify API ingress points. More than likely, you will want to use Dynamic Application Security Testing (DAST), Interactive Application Security Testing (IAST), or Feedback-Based Fuzzing. DAST tools are deployed later in the development cycle as they require the code to be running, but they are good for testing an API from an attacker’s perspective. IAST essentially combines SAST and DAST to give the benefit of access to all of the code, with the additional context of runtime information, to reduce the number of false positives. Finally, fuzzing is a type of testing in which inputs are provided to an application to see if any fail the program. The goal is to find bugs before an attacker does. These inputs can be random, a kind of brute-force fuzzing, but in the case of feedback-based fuzzing, an algorithm is used to increase the amount of code tested and evolve with results. Fuzzing is helpful for testing unexpected edge cases with fewer false positives.
RH-ISAC members have exclusive access to resources that can help with API security. For example, the Software Security Working Group meets to discuss topics like security tooling, DevSecOps, securing the SDCL, and security by design. Members also have access to sharing platforms such as Member Exchange, where they can seek advice from fellow members on specific topics, such as this RFI on API security assessments. Not an RH-ISAC member? Learn more about how being a part of the RH-ISAC’s member community can benefit you.