Updated: Sep 15, 2022
*** Based on the work of Dave Wheeler, my friend and co-author, in our book - The IoT Architect's Guide to Security & Privacy.
Software security can seem a little mysterious if it's not your area of expertise. Yes, there are many security nuances and gotchas with various technologies, and I wouldn't dare to claim to be some "across-the-board" security expert. However, I want to show that the core principles that guide software security, and in this particular article, secure design, are pretty simple once you discover them.
Why We Need Secure Design Principles
Since the early days of computing, secure design principles have been around, as far back as the 1960s. They are the design patterns that help you avoid common mistakes when architecting and building security into software or other computer systems. In essence, as you implement security controls to protect your SaaS (and any computing system) from cyberattackers, you can employ the principles below to ensure robust and resilient security.
7 Secure Design Principles for SaaS
Principle 1: Open Design
What it means: Your security design should not depend on any secret constructions. Even if the design underpinning a security feature is published, it should not weaken the security of your system.
An Example: For a B2B SaaS platform with authenticated API integrations to various partners and customers, the security of the authentication should not be based on undisclosed authentication protocols and flows. Rather, even if your partners or customers know how the authentication works under the hood - and most diligent customers will want to know - it shouldn't make you more susceptible to a hack by a malicious customer. Achieving this will require using open, trusted, and tested protocols for authentication and cryptography.
Principle 2: Economy of Mechanism
What it means: This is KISS - the Keep It Simple Stupid Principle. The KISS principle states that most systems work best if they are kept simple rather than made complicated; therefore, simplicity should be a key goal in design, and unnecessary complexity should be avoided.
An example: Many of us will likely relate to this... a SaaS startup wants to process payments from multiple banks and via various payment methods. There are two options, implement your own payment processing libraries or keep things simple by using a platform like Stripe. Yes, there are scenarios where the SaaS startup has good cause to write their payment libraries, they may even be a payment processing startup. But, for most other startups the complexity, risk, and cost of building a secure payments library are not worth it.
Principle 3: Fail-Safe Default
What it means: All security-sensitive operations should be designed to allow access or give permissions only when certain conditions are met (e.g., presenting the right password or holding a proper key), and fail otherwise.
An example: Consider a Smart Home platform that processes inputs from multiple sensors and edge gateways. There are many access control decisions involved here: Should a particular sensor be allowed to upload data to a certain gateway? Can this gateway connect to this cloud system? Should this cloud system be allowed to perform device management on this device? All these access controls should always be implemented as fail-safe defaults, preferably using cryptographic techniques as the underlying decision factor. This could be a cryptographic hash of a password, or better, an authenticated TLS connection using an asymmetric key pair.
Principle 4: Separation of Privilege
What it means: Two or more independent mechanisms should be used to control access to highly sensitive data or functions. This means two independent failures are required to overcome the access protection mechanism.
An example: Two-factor authentication (2FA) is a great example of this. For example,
you may need both a password and some access token sent via text message to your phone to log into your bank account.
Principle 5: Complete Mediation
What it means: There must be no caching of access control decisions, instead each access control decision must be performed at the time of access to ensure that
the access rights have not changed. This is directly related to the time-of-check-time-of-use (TOCTOU) attack. TOCTOU is the window of time between an executed security check and the actual use of the object that was checked, which is the amount of time an adversary has to execute an attack.
An example: In the case of integrity checks on containers, the check is performed
at container launch time. This means that any time after launch, a buffer overflow attack can dynamically change the code inside the executing container, and the changes will not be detected and will not have an effect on access control decisions. One solution to this problem is to leverage microservices, where the container itself is a very tiny service that is brought up only when an action needs to be performed and is then shut down. This limits the time of attack only to the time the microservice is executing.
Principle 6: Least Privilege
What it Means: The least privilege principle states that a program (or person) should only have the privileges they require and no other privileges. This principle is most often violated by running a process as the administrator or root.
An example: Consider a DevOps build chain where a platform like CircleCI is used to deploy your code to your cloud tenancy(i.e. AWS/Azure/ GCP). CircleCI needs access to view your code repo and download code, but it should have no access to update or add code. Providing those extra privileges to Circle CI significantly increases the risk to your platform if your CircleCI instance or service, gets compromised.
Principle 7: Defense-in-Depth
What it means: If a security mitigation is warranted in a system to protect an asset, there should be a layering of independent defenses so that an attacker cannot gain access to an asset by overcoming a single defensive measure. The layering of independent defenses makes a system significantly more robust against attack.
An example: If you were building a digital wallet SaaS platform that allows your users to store and transact cryptocurrencies i.e. Ethereum, Bitcoin, etc, the wallet and particularly its contents are assets that the platform must protect. One layer of defense is to ensure that all users to the platform are authenticated via two-factor authentication before they can make any transactions. Another layer of defense is to ensure that the cryptographic (private) key that protects each user's digital wallet is stored in a protected keyvault - like Azure Keyvault, AWS KMS, or GCP KMS, such that users can transact without the need to retrieve or expose their private key. A further layer of defense is to store the private key in an HSM (Hardware Security Module)-backed key vault, such that both the storage and usage of the private keys occur within a highly protected and isolated hardware device that reduces the possibility of tampering.
There you have it, some core principles that anyone can apply to secure the design of SaaS. Yes, the nuances of some technologies or problem spaces may make things more complex, but these principles will be a worthy guide to securing your SaaS.
Did I leave out some secure design principles?? Please feel free to share in the comments.
The Secure Design Workshop for SaaS Startups
Are you interested in learning how to put these principles to work in your product and your software architecture? We recently launched a uniquely practical Secure Design Workshop for innovative SaaS startups - this could be startup businesses or startups within established businesses. In a 3-hour focus session, Resilient's experts come alongside your team to analyze your product and architecture, identify critical assets, reveal attacker profiles and their attack points, and finally... identify secure and usable mitigations.