Blog

API Security Checklist: Part 2

We continue the journey on understanding the best practices applicable towards secure application development, enforced through an API specification. In the first article in this 3-part series, we learned about five best practices specific to how the security field as well as arrays should be managed in an API request and response. In this article, we outline further aspects of security, particularly how string data types should be managed.

 

We want to remind the reader that the goal is to ensure a secure API design by implementing the best practices within the OpenAPI specifications. A secure API design ensures a robust application.

 

Let’s jump in.

Five Additional Best Practices for Secure API Design

 

Just to recap some preliminary information for what we are about to discuss: the best practices discovered in this series is enforced using the CloudVector static risk assessment tool. The tool analyzes a Swagger (OpenAPI v2) specification to look for vulnerabilities/design issues across 30+ pre-defined checks. In addition to identifying what the issue is, the tool also points to where in the specification does the issue occur and the impact that entails and hence can be remediated conveniently. The tool also labels every identified issue with a corresponding severity (Critical/High/Medium/Low) and categorizes the issue as belonging to a Security, Data, or Format category. We note the severity and category for every issue discussed in this series.

 

Now, let’s really jump in.

Issue #6: String objects should have a pattern defined.

cvtags: Severity-Medium, Category-Data

 

What: In an API specification, an API endpoint may use string type objects as either a parameter or the individual elements of the array data structure. This issue occurs when such string objects do not have a strict pattern defined. Such a pattern may be defined using the pattern field which occurs at the same level as the type field. Figure 1 shows an example of the pattern field, which if absent, results in a violation.

 

Figure 1

 

Impact: Not specifying the pattern field allows attackers to input arbitrary strings into the affected object. Arbitrary string inputs can trigger buffer overflow or injection attacks possibly giving the attacker privileged access to the compromised endpoint. Arbitrary strings can also cause the application to crash thereby denying service to the client.

 

Remediation: To avoid such a violation and keep the API assets secure, it is recommended that the specification developer specify the pattern to which the string object must adhere to. The next issue discusses more about the kind of pattern that should be specified.

Issue #7: String object pattern is unrestricted.

cvtags: Severity-Medium, Category-Data

 

What: The previous specification principle required the API developer to specify the pattern field. This issue requires that the pattern field be specified such that it imposes tight restrictions on the kind of input strings exchanged with the interacting API client. A violation of such a rule would look something like in Figure 1 where the pattern of input string has been defined but the pattern basically suggests that the parameter prodcode can be any arbitrary string.

 

Figure 2

 

Impact: The impact of this violation is similar to the previous issue where an unrestricted pattern will result in the attacker successfully exploiting the API endpoint.

 

Remediation: The strictest possible pattern must be supplied for the corresponding object. For example, in Figure 2, the parameter prodcode is identified exactly by a seven letter alphanumeric string and therefore the corresponding specified pattern is “^[a-z0-9]{7}$”. Therefore, injection input strings which are typically longer, can now be ignored or handled appropriately.

Issue #8: String objects should have a maxLength defined.

cvtags: Severity-Medium, Category-Data

 

What: Okay, so we learned that string objects should have a restricted pattern specified to fend off exploitation attempts. Here we lay out the scenario where the pattern itself cannot become restricted but we still want to improve the security around the target object. 

 

This best practice is enforced by the CloudVector tool when, analogous to the pattern field, the maxLength field is missing for the target string object. The maxLength field should be specified as in Figure 3.

 

Figure 3

 

Impact: The motivation for limiting the user input with the maxLength field follows the theme as noted for issues #5 and #6 above. An unfettered input could be exploited.

 

Remediation: Consider an example where the input parameter is a string object which expects textual input, say a user account password. In such a scenario, the corresponding pattern would require the password by an alphanumeric string with special characters included; so basically all characters. However, to limit an attacker from abusing this parameter, we should specify the maximum number of characters as 10. This significantly improves the security since injection commands or exploitation strings would usually exceed 10 characters.

Issue #9: Invalid or insecure authorization URL.

cvtags: Severity-High, Category-Security

 

What: API endpoints that use the OAuth scheme to authorize users accessing the application, need to specify the corresponding authorization URL. This authorization URL grants the necessary token for application access. Therefore, specifying an invalid or insecure authorization URL results in a violation identified by our tool. Figure 4 shows an example of an insecure authorization URL.

 

Figure 4

 

Impact: Using an invalid authorization URL (say invalid domain or protocol) results in the service disruption, resulting in bad user experience. An insecure authorization scheme, however, can be more damaging. As in Figure 4, the use of HTTP protocol instead of the HTTPS scheme allows a snooping malware to easily steal user credentials which could either be in the form of username-password, or it could be the OAuth token used to access APIs.

 

Remediation: Always ensure that the authorization URL used to support the API is both valid and secure.

Issue #10: Specify the content type used in request/response.

cvtags: Severity-High, Category-Security

 

What: Content type specified by an API helps the client understand the format of data that needs to be sent to the API endpoint (the server) or the format of data from the server. In an API specification, the former is specified by the API using the field consumes which lists the content types that an API can successfully consume. For example, the API endpoint may consume one or a combination of mime-types such as application/json, application/graphql, application/text etc. Similarly, the type of content produced by the API is specified through the field produces.

 

Figure 5

 

Figure 5 shows examples of having the produces and consumes field in an API specification. Each field is a list of supported mime-types. Note that both produces and consumes fields are present but only produces has been specified. Best practice dictates that both fields be present and be non-empty.

 

Impact: Consider the consumes field first. If the API Swagger specification fails to specify this field or leaves it empty, this would imply that the application can accept arbitrary input. Reiterating the theme mentioned earlier about how unfettered input can be used to exploit the endpoint through buffer overflow or a curated exploit string, specifying the expected content type is a good practice. The same argument holds on the client-side. If the produces field is absent and hence the API HTTP response fails to populate the Content-type field, the client would be at a loss on what to expect. Security sensitive clients may not entertain responses with absent fields such as the Content-type.

 

Remediation: Both produces and consumes fields should be specified with the exact data types that will be honored.

Summary

We discussed five more best practices to tighten up your API specification and hence making your application development process more secure. The best practices can either be implemented manually or be enforced through an API specification tool. The enforcement integrated with the CI/CD pipeline makes the API development process significantly more secure, thereby truly resonating with the Shift-left paradigm.

 

In the next article, we close out with the final five best practices that should be followed for securing APIs. Stay tuned

Sandeep Yadav

Sandeep Yadav

Sandeep Yadav is the Director of Data Science at CloudVector. He has over a decade of experience in building threat detection systems using machine learning and deep learning. Sandeep has authored several publications in top-tier IEEE/ACM conferences and journals, and is a co-inventor of multiple patents. At CloudVector, Sandeep leads the effort for developing effective ML/DL solutions to API-based threat vectors.