The Lack of Security Layers in SaaS
Running applications using a cloud service should be far more secure than running the same apps on your own servers. In theory, the cloud company will keep everything up-to-date, deal with upgrades and migrations, and understand deeply what security is needed.
But if the cloud app holds sensitive data, then it’s a rich target. If breached, an attacker will likely get the data of many customers. One vulnerability in the code, the infrastructure configuration, or any unexpected behavior at the intersection of complex systems, and an attacker can get at that data. The resulting breach can be devastating for both the cloud app company and their customers.
This blog will look at the typical approach to securing cloud apps, the weaknesses inherent in it, and will consider what can be done to improve things.
The Typical SaaS Architecture
In most cases, a SaaS app will consist of one or more application-layer services that talk to one or more backend data stores. Each application-layer service enforces permissions to make sure that the user making a request only gets back the data that he or she is allowed to see. The data stores don’t usually enforce this or even know who the end user is that is making the request.
Because developers make mistakes, and because of attacks like SQL injections, most SaaS companies will purchase a security solution that sits out in front of the application. Typically, that means a network-layer firewall plus a web application firewall (WAF). It’s the responsibility of the latter to block common attacks targeting web applications.
After traffic is scanned, it travels onward to some kind of ingress controller or load balancer. This is responsible for routing traffic to the appropriate services, limiting direct access to some service endpoints, and helping the app scale by adding more instances of the services. (Note: sometimes the WAF comes after the load balancer.)
Finally, the individual services will typically talk to the data stores as needed. Here’s what this looks like:
If you’re an attacker looking at this, what you’ll see is an outer shell with security rules that need to be evaded and a set of services each of which likely contains yet-to-be-discovered vulnerabilities. That’s two layers of security to get through in order to get to the good stuff.
The Overreliance on WAFs
So that Web Application Firewall (WAF) carries a lot of the burden. But here’s the thing: not only are WAF evasion and bypass techniques plentiful, but most don’t require much skill on the part of the hacker.
Even worse, WAFs can do more harm than good. For example:
- They reduce performance;
- they produce false positives that break your app (causing you to shut off some of the protections that you may need);
- they have their own vulnerabilities that can give an attacker a foothold in your network;
- they promote an attitude in developers that makes security someone else’s problem;
- and they introduce added complexity that enables attacks like desyncs and rewrites.
Some security researchers, like those who wrote about the desync attacks linked above, believe WAFs are actively harmful. I think they still have value and I wouldn’t run a service without one, but they do introduce some risks even as they mitigate others. The lesson here: if you lean too heavily on your WAF, you’ll fall over.
But maybe the cloud app is well-designed, with flawless permissions enforcement, always validated inputs, and no vulnerabilities. And the libraries and other software that the app uses are equally bulletproof. And the continuous stream of changes to the stack don’t adversely affect its security. And pigs might fly.
The Swiss Cheese Model
There’s a concept in risk analysis that helps to visualize layers of safety and risk reduction. The idea is that any single measure will inherently be imperfect, but layered together, a risk can be mitigated. For example, you might think of a seatbelt as a slice of cheese. An airbag is another. A crumple zone is a third. ABS brakes are a fourth. The goal of each of these measures is to prevent deaths in the case of a car accident. A death only occurs if the holes (the weaknesses) in each measure all line up and occur at the same time. This is called the swiss cheese model.
Essentially this is a way to visualize one of the core pillars of security by design: Defense in Depth. So why, then, are there only two layers of meaningful security between an attacker and the data they seek to reach in the typical SaaS app? Why do most cloud app companies consider it “good enough” to transparently encrypt the data in its data stores, when that encryption does nothing to prevent unauthorized access to the data if an application is compromised?
It’s time to add some more cheese to SaaS apps.
Application-layer Encryption (ALE)
One layer to add sits between the application and the data stores, and it’s often called application-layer or application-level encryption (ALE). The key concept is that data is encrypted before being stored, which prevents someone with direct access to a database from being able to browse the encrypted data.
ALE can take many forms, but at its best, it adds another layer of permissioning and data segmentation to the data. That is, it can be used to virtually isolate sets of data so that an application breach does not immediately expose all the data. Instead, a layer remains that contains the blast radius from the application vulnerabilities. It will also prevent any access to sensitive data if the network is the exploited component or the hacker gets into the data store.
Using our earlier systems diagram, it might look something like this:
Segmenting Data by Service or by Tenant
To segment data, you use keys and restricted access to those keys to create the virtual isolation. For example, you could restrict Service 1 to only access the data in the database that it needs to do its job. Other data stored in the database or in the file store would be meaningless to it. And you can do this on a per-row or per-column basis.
In a multi-tenant SaaS world, you can use a different master key for each and every tenant (customer) and use an ALE solution that only allows the fetching of data for one tenant at a time.
This extra precaution is a game changer in terms of what happens when a breach occurs. And it’s even more of a game changer if the SaaS app lets their customers hold their own master keys and monitor access of their data. The customers retain control of that data and can revoke access at any time.
It’s Time For Action
It’s time that we as a software industry stop hoping for magic vendor solutions that sit outside the application and intercept all hacking attempts. At best, they work partially and at worst, they’re part of the problem. Applications need to add their own layers of security, and there’s no more meaningful component to add than a data protection layer.