The proliferation of APIs today is astonishing. According to a recent report, the number of active APIs will approach 1.7 billion by 2030. You might expect that the majority of those APIs would be resistant to attacks or vulnerabilities; however, that is not necessarily the case. In fact, a major study from RapidAPI on the state of enterprise APIs revealed a rather distressing lack of consistent policy enforcement and visibility across all APIs. Many of those APIs might expose parts that are undocumented, which is a great concern among security teams.
This article explores the fundamental reasons why an API can become insecure and discusses ways to reduce the attack surface.
Documenting APIs comes with inherent difficulties. The main problem areas include ambiguity of exposed functionality, incomplete or undocumented content, and incorrect responses. Development teams rely on tools like Swagger to help them document their APIs and use automation to mitigate some of those issues.
Swagger is not a panacea, however, and using Swagger/OpenAPI for API development does not protect you against all vulnerabilities. Recent research conducted by Soufian El Yadmani of Cybersprint found many flaws in this technology, including many vulnerabilities listed in the OWASP API Top 10.
For example, issues can happen when a web framework is integrated with Swagger. Developers using the FastAPI framework can receive automatically generated Swagger UI fields from the code without declaring the API specification. This works fine on paper, but it might not work with your particular business requirements. The CRUD model might return a different result based on certain circumstances, for instance, or use a different way of calculating the end result that deviates from a typical case. The framework might be unable to introspect the correct result and rely instead on manual intervention. In this case, developers will have to completely own the dependencies and generated documentation to ensure that they match the expected outcome.
In addition, Swagger generates complex code that has little opportunity for customization, which makes it inconvenient to use. For example, if hypermedia links are missing from the response, developers might try to intervene by writing custom queries that deviate from the spec, thereby increasing the risk of producing undocumented responses.
Overall, the hardest part is establishing proper workflows for working with Swagger in the optimal way – writing specs in YAML, implementing the specs, and writing unit tests that conform with those specs. The API maintainer’s job is to make sure that they don’t deviate from the supported features and that they keep the spec as an authoritative source of truth.
There are many reasons why APIs are hard to keep track of, and therefore hard to support at scale, but they all relate to technical debt. Working on many products as part of a broader ecosystem is a very typical scenario. Some parts of the system might be unknown due to a change in business priorities and focus, when some API services were neglected and forgotten – until they failed to work. This is an example of code ownership debt.
Another type of technical debt is people debt. This happens when you allow developers to work on critical API systems for a long time and then they decide to resign from the company. The domain experience that these people acquired when building those systems may be lost to future maintainers unless there is a good handover process. Having many API services and no one who understands how they work significantly contributes to the initial problem.
The issue becomes even bigger when you introduce architectural debt by implementing APIs using microservices. Let’s explain.
APIs and microservices are directly related. As you develop applications using microservices, you create highly decoupled services that enclose their own domain and communicate with each other using APIs. For example, a user microservice needs to communicate with the auth microservice to authenticate the user before responding to a request to view that user’s profile. This communication dictates the use of an API contract between each microservice. In addition, API gateways can be used to aggregate multiple APIs under a single namespace, which helps maintain observability and centralized monitoring at a fundamental level.
More real-world domains may need many microservices. In practice, that means having a separate API layer behind each microservice – and each one has its own attack surface. It’s not unusual to have hundreds of microservices that each expose OpenAPI interfaces. This leads to what is known as API sprawl. In this case, the sheer number of services makes things harder to maintain. It’s very common for businesses to use APIs without tracking when or where they are used, which makes it harder to keep track of their security risks.
It is a well-known fact that you cannot secure something when you don’t know it exists. But achieving continuous runtime visibility into all APIs is not trivial. It requires that you understand the exposed parts of the API in depth and that you document the obscure sections, run static code analyzers, and subject the application to security testing. This is mandatory, since the failure to record and secure these parts is very dangerous.
APIs are already extremely susceptible to many kinds of attacks. Undoubtedly, there is no limit to what attackers can use when it comes to stealing sensitive data for malicious purposes. Here are some examples of attacks that you may encounter:
- DDoS: Attackers can target unknown parts of your APIs to do the maximum damage. They can overload the system with terabytes of bandwidth if they’re successful, and you won’t know what hit you. It’s therefore important to safeguard against DDoS attacks on each exposed part of your APIs.
- Innocuous access: Hidden or undocumented parts of your API can be easier to exploit. By using unknown endpoints, for example, attackers can dig in quickly and gain unauthorized access without someone detecting anything suspicious. Unless the traffic from those endpoints is more consistent, it will be harder for the security teams to recognise the danger.
- Injection: API endpoints that are vulnerable to injection attacks (SQL, XSS, and so on) can help attackers expose sensitive data, leak credentials, and gain insights into how to attack the infrastructure. If the API under attack is unknown or undocumented, you will lose valuable time trying to figure out how to safeguard it.
Take extra care when you develop and expose APIs – especially the ones that are used for public access. These can be used as target practice for all sorts of attacks. Conducting a solid security assessment of your APIs will position you one step ahead of any future attacks.
Just because you use Swagger, follow the best practices for documentation, and lead by example does not mean that your APIs are secure by default. It literally takes a village to achieve a superior level of security – mainly because of the inherent difficulty of covering the attack surface of your APIs. This is why you need to establish an end-to-end API security strategy, complete with security testing, extensive discovery of available APIs, and the use of modern tooling and monitoring services. With some effort, you will improve the security posture of your APIs without hurting their overall performance.
About the Author
Theo Despoudis is a Senior Software Engineer, a consultant and an experienced mentor. He has a keen interest in Open Source software Architectures, Cloud Computing, best practices and functional programming. He occasionally blogs on several publishing platforms and enjoys creating projects from inspiration. Follow him on Twitter @nerdokto.
To learn more about how Checkmarx One™ Application Security Platform can help you secure your applications, request a 14-day free trial here.