Adopting a Shift-left Approach
Securing API Endpoints is critical for securing applications. This requires security products to monitor a diverse and comprehensive set of components supporting the application. Some security products evaluate the behavior of application traffic, some focus on the post-development application code, and others look to embed security at the application genesis itself, and so on. Since there is no single security platform that combines all of these solutions, customers have prioritized a focus on employing individual tools that protect various paradigms of the attack surface. One such paradigm that has received keen interest is the shift-left approach. In this paradigm, the security of an application at the design, development, and test stage comes to the forefront rather than addressing it post deployment of the application to production. As per System Science Institute at IBM the cost to fix issues during the design phase is 1x compared to the cost of fixing issues post deployment to production which is 100x.
One of the frameworks to secure APIs in the Shift-Left paradigm is Static Application Security Testing (SAST). CloudVector provides a powerful tool as part of the SAST arsenal to identify vulnerabilities and design issues within application specifications. An application specification lays out the properties, limitations, and configurations associated with the APIs christened by an application. The standard for writing these specifications, as adopted by application/API developers, has been defined by OpenAPI (v2 or v3). v2 is also called Swagger. For the purpose of this article, we will consider examples specific to Swagger.
API properties defined in the Swagger spec identify the behavior and the security aspects of an API. As an example, the schemes field defined for an API GET method, describes what transport security schemes (i.e., http(s), ws(s)) should be enforced by the application developer. This article aims to educate the reader on some of the best practices that API Swagger specifications should enforce to enable a secure design before application development.
Five ways to make APIs more secure
In our discussion of improving the secure API design through Swagger spec evaluation, we should mention that the CloudVector static risk assessment tool can help with this process by analyzing an existing Swagger 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. ‘Nuf said. Let’s jump into some of the best practices that a developer can adopt at the time of API design.
Issue #1: Absence of the security field both globally and for the operation object.
cvtags: Severity-Critical, Category-Security
What: This issue suggests that the security field is absent globally and for the corresponding API operation (GET/POST/PUT etc.) where the issue occurs. Figure 1 shows an example of a security field when it is present for the API /products GET operation. This is the correct way to do it, the incorrect approach would have a missing field.
Note that the figure does not show the absence of the global security field.
Impact: Absence of the security field at both the global and the operation level communicates that the developer does not need to enforce any authentication/authorization requirements for the API in question. Absent auth security may allow attackers to freely access private data. Rogue actors may succeed in compromising the endpoint by gaining authorization to a wide-variety of data taps, thereby creating greater risks for the target organization.
Remediation: The authentication mechanisms and authorization scopes should be defined meticulously for every API. In the absence of a per-API security specification, a global security specification should be defined.
Issue #2: The items object should have the type field defined.
cvtags: Severity-High, Category-Data
What: The items object is specified when the target object is an array. The items object captures the properties of individual array elements. This specific issue, however, occurs when the data type of every item element is not defined. Here is an example of having an item with a data type specified. Again, this figure shows the correct approach, the wrong way would have the missing data type.
Impact: Absence of a data type specification can allow the API to consume a variety of content. This, in turn, provides freedom to a hacker who can fuzz inputs, perhaps to exploit a buffer overflow, cause a memory corruption, or trigger data leakage from the API endpoint in a manner similar to an SQL injection.
Remediation: Always specify the exact data types expected for the items’ elements.
Issue #3: Array type parameter objects should have the items field defined.
cvtags: Severity-Medium, Category-Format
What: Referring to Figure 2 again, we note that the 3rd parameter (named “status”) is an array type. This issue states that if the object is an array type, then the items field should be defined as well. We note that for the parameter “status” the items field is indeed present.
Impact: If the items object is absent, then the corresponding properties of the input elements are absent as well. With issue #2, we highlighted the consequences of absent data type within the items field. If each element within the array is, say, an integer, then the absent items field fails to describe the format or perhaps the number of elements within the array (captured using the maxItems field). Absence of such properties can, as a result, open security holes where the attacker is able to abuse the affected parameter object for unrestricted access to data or the endpoint.
Remediation: Specify the items field for the parameters object.
Issue #4: Credentials should not be transported in cleartext. Use a secure scheme.
cvtags: Severity-Medium, Category-Security
What: A schemes field identifies the transfer protocol for the operation. Figure 3 shows that the GET operation of the API /products supports https based transfer. Alternatively (and additionally), the supported schemes include wss, http, or ws. The issue occurs when either http or ws is used as a scheme, since neither of them use TLS security.
Impact: Using an insecure scheme breaches the confidentiality contract between the client and the server and therefore the ongoing communication may be easily readable by a third party.
Remediation: Use only https or wss scheme.
Issue #5: Array parameter objects should have the maxItems field defined.
cvtags: Severity-Medium, Category-Data
What: We again refer to Figure 2 for understanding the issue. Earlier in issue #3, we highlighted how absence of the items field can be abused. This issue instead states that the absence of another field maxItems is a medium-severity violation. maxItems limits the number of elements that may be present when an HTTP request containing the target parameter is made. Figure 2 clamps the maximum number of elements in the array as one.
Impact: If the maxItems field is absent, the parameter object may be abused with innumerable elements potentially DoSing the API endpoint. Depending upon the API endpoint implementation, excessive number of elements can also trigger a buffer overflow leading to further security issues.
Remediation: Always define the number of items expected for the array object.
The above described issues are only a subset of the issues that can be discovered by the CloudVector static risk assessment tool. Following the best practices described here helps guide the secure code development process. On the other hand, issues found during the API design should trigger actions for resolution or containment. As an example, the CloudVector tool integrates within the dev CI/CD pipelines and can be configured such that specs containing identified issues never make it to the implementation stage. Want to get a quick analysis of one of your Swagger specs, request it here.