DX, API Design & Documentation

Secure By Design

221views

Jose Haro Peralta is the founder of microapis.io. He is an instructor and a consultant. He helps organizations build distributed systems using microservices platforms and build all the integrations between components through APIs. In this article, he talks about security by design and how it applies to APIs.

API security by design

API security by design is an approach that encourages us to shift left our security strategy by incorporating security concerns from the design. We incorporate security into every step of the API development cycle to ensure our implementation and delivery process is safe and secure.

The idea is to approach API design, development, and operations from a security-by-design perspective, ensuring that every step we take in the process is secure.

This allows us to deliver foundationally secure APIs designed to be secure by design and conductive to security. So, they will rule out the use of flows that are not conducive to security, and they will not expose input to our users that can be used for malicious purposes. It encourages us to address security early, which is generally good. But most importantly, it allows us to avoid costly changes to our API.

If you picture the typical API development process, we start with a design stage. We go through implementation, deploy to an environment, and test the integration with the clients to ensure there are no issues in that integration. And then, we run about 20 security tests against the API. If we find issues in the API, we have to address those issues; we have to change the API, go back to the beginning of the process, redesign, re-implement, redeploy, test, and integrate. If anything changes, we have to again go through the entire process.

This is a very expensive process of tackling security issues in our APIs. The idea of security by design is how we can prevent many of these problems later on if we address them at the beginning. We will still encounter issues that we can’t tackle everything from security by design; there are some issues that we will only find in deployment and the right environment. But we will find fewer issues.

Now, to be able to do this, we need one very important requirement. This is called the golden rule of API security or API security 101; you can’t protect what you don’t know. You need API documentation and a formal specification. This is not a tutorial.

A formal specification accurately describes the API; it tells you exactly how it works. As a consumer, I can trust that specification. I can use it to validate my code to integrate with your API. It allows us to apply security by design to our APIs.

Sequential IDs

Sequential IDs are IDs that follow a predictable pattern of identifying objects. Most database agents natively support them, they are easy to work with, and they are easy to reason about and to debug. They are very efficient for data indexing and retrieval. But they are also a great security risk if we expose them directly through the API. If a user figures out the predictable pattern, he can get hold of resources that do not belong to him. If that happens, we will be in a broken object-level authorization (BOLA) situation, and we want to prevent that.

From a security-by-design perspective, hiding those IDs is the way to prevent that. First, we don’t use those sequential IDs in our database if we can. But if we have to use them, we use something like a hashing function to mask the original value and expose something else to using something consistent though some a permanent identifier. Still, it is different because of the fact because of the hashing function.

Flexible Schemas

Flexible schemas are the ability to compose a payload with different properties. We can have flexible schemas via undeclared properties or optional properties. This opens the door for attacks, most prominently to mass assignment and data corruption attacks.

Undeclared properties haven’t been declared as part of the schema. Our schemas are not restricted or exclusive of the properties we’ve declared. They allow the presence of additional properties in the payload, and those are valid payloads. Mass assignment is a vulnerability that allows malicious users to override properties they shouldn’t be able to modify. To prevent this, use strict schemas and DTOs to transfer data between layers explicitly.

The second type of flexible schema is with optional properties. This is the ability to decide which properties we set from the payload schema. This gives our users flexibility and allows us to combine different models within the same schema. But if some user passes code that looks valid to the API but may be invalid for the database and break the database.

So, to prevent this, we must split the model and have different schemas for each model. The core properties of a model should never be optional. Also, we must ensure that we don’t let the user mess around by setting additional properties to false.

Unbound parameters

This applies to anything from integers to strings to arrays and the ability of a user to set very big values for those parameters. This opens the door for big integer attacks, large payload attacks, pagination attacks, etc. To stop this, we must have constraints on such parameters. Also, we must set additional properties to false to prevent the user from manipulating these payloads any further.

Exposing server-side properties in user input

Server-side/read-only properties are set and managed by the server, which is usually sensitive data, like IDs, status, etc. A user can manipulate these requests, which will be considered a valid payload but can be used maliciously.

To prevent this vulnerability, we can use two different strategies. We can split the schema into two different models or set the properties specific to the training endpoint as read-only properties. Of course, we also want to put constraints on the values in the input of a payload; we want to ensure the user cannot set funny values for the amount or the destination account. There’s a specific format for that. We must ensure they use constant additional properties in the payload.

Tackling issues at scale

A typical API specification will have hundreds of thousands of lines. We cannot review this manually line-by-line. So, this process must be automated. We must distinguish between design testing and runtime testing. Runtime testing means against a running server. It can be a local server, or it can be a server in a deployed environment.

We can use a vast spectrum of tools for testing. Some are Schemathesis, Fencer for runtime testing, and Spectral for design testing.

To conclude, test your code, and you may find many errors, which can seem scary. But it is not that difficult to address these problems. Have a formal API specification because you cannot protect what you don’t know. Use a test suite to run tests and then fix the issues.

Jose Haro Peralta

Jose Haro Peralta

Founder, Author, Instructor at microapis.io
I'm an architecture consultant, author, instructor, and speaker based in London. I'm the author of Microservice APIs (Manning, 2022 - http://mng.bz/0wmx) and the founder of microapis.io Over the past years, I've worked with businesses from all over the world to help them architect microservices platforms, deliver API integrations, automate their processes and infrastructure, design and implement ETLs and Data Pipelines, productionize Machine Learning through MLOPs, and improve the quality of their software. My previous clients range from small startups to large corporations in the financial industry, insurtech, IoT, and retail.

APIdays | Events | News | Intelligence

Attend APIdays conferences

The Worlds leading API Conferences:

Singapore, Zurich, Helsinki, Amsterdam, San Francisco, Sydney, Barcelona, London, Paris.

Get the API Landscape

The essential 1,000+ companies

Get the API Landscape
Industry Reports

Download our free reports

The State Of Api Documentation: 2017 Edition
  • State of API Documentation
  • The State of Banking APIs
  • GraphQL: all your queries answered
  • APIE Serverless Architecture