We Need the Controller Layer Back!

A couple days ago, I gave an API security workshop to highlight the OWASP Top 10 issues for APIs and some of the mistakes we keep doing at development time and pay for at runtime.

Many of the issues related to data, such as improper data filtering, mass assignment or excessive data exposure, could be avoided if data was controlled in a specific layer of the architecture. When I started in IT, a proper application would respect the MVC architecture: we had a model (data), a view (UI) and a controller layer. Never would have we exposed the data straight to the UI and hoped for the best!

But here is what we see now: we have data in a MongoDB database, we point a tool at it that exposes CRUD operations on top and we call the output a REST API (for the record, that is not a REST API, but it’s matter for another blog). Then we expose that API to the world and let the UI filter and manipulate the information. What are the results of that approach?

  • We expose all the resource data (say a customer object) even if the UI only needs a fraction of the information.
  • We have CRUD access (in HTTP terms GET, POST, PATCH, DELETE) even if only GET is needed.
  • We expose the internal IDs of resources, straight from the database.

Those are the issues at the core of the A1, A3, A5 and A6 OWASP Top 10 issues for APIs. Here is what can happen:

  • Anyone can see the data exposed by the API by using the developer tools of any browser or a web proxy. Consider that information as public.
  • That data can be used to update information via mass assignment: if I have the full JSON structure returned by a GET, I can try to update data using that same structure via a POST/PATCH.
  • A hacker can use the information to find interesting data such as internal IDs and retrieve information by guessing internal IDs sequences (1234, 1235, 1236,…).
  • We do not validate who has access to what. As long as a proper access token is presented, we let the user in.

How can we avoid this? By getting back to good development practices!

  1. Create a data layer, i.e. internal data APIs, which encapsulate the data access (good old’ DAOs).
  2. Isolate that data layer behind a process/controller layer: that layer accesses the data, formats it and filters it based on the usage
  3. Create a proper front layer (this is where the REST API lies), which returns the data as *needed* by the UI layer. That front layer is also responsible for presenting different APIs depending on the consumers (say internal users and partners).

What does that controller layer do?

  • Verify that the user has proper access to the data : this will protect you from issues whereby a valid token is used to access data not belonging to the user. Typical example is a phone company API allowing to retrieve a user profile from the phone number, as long as the caller presented a valid access token.
  • De-correlate internal IDs from external IDs : if we take the same example as before, use the phone number at login time or authentication time to issue an access token, but then exchange it for a UUID, which are not subject to being guessed. Uber just learned this the hard way.
  • Return data based on the expected usage.
  • Block unwanted API calls (bad verbs, paths, improper content-type, etc.)
  • Block requests and responses where the data does not conform to the contract.

What are the other benefits?

  • You can separate those layers: if we take the example of a Kubernetes deployment, each layer can run in a different namespace, with different node pools, adding another layer of security by making sure you cannot reach the data layer from the front layer.
  • You can tune/scale them separately: accessing data is probably more memory consuming than CPU consuming. Processing layer is probably the reverse.

Our solution can play a critical role in that controller layer: by enforcing the OpenAPI contract, we ensure that APIs do not accept/return unwanted data, validate tokens and, coupled with 3rd party authorization services, enforce that the caller is properly authorized to access such data.

Lets add that controller layer back into our architectures!

If you want to see how the 42Crunch platform could play a key role for your APIs protection, request a demo now!

For news on all things API – visit our community site APIsecurity.io and sign up for the weekly newsletter.