Security is about protecting assets that might be vulnerable to direct and indirect attacks by an intruder, or by system failures and errors.
To effectively protect your assets and improve the security of your apps, and fix security issues, you first need to learn about the basic concepts related to security.
The most general concepts of computer security are confidentiality, integrity, and availability.
ConfidentialityIt ensures that authorized subjects who are not authorized do not have access to the asset. A data breach is a typical confidentiality issue.IntegrityIt ensures that the asset you are protecting, and that holds value for you, cannot be altered by an attacker. Ransomware attacks compromise your data, without the need to access it.AvailabilityIt ensures that the protected asset, that produces value for you, can be accessed by subjects who are authorized to access it. A DDoS attack is a clear attack to availability.
The validity of these concepts in your apps can be supported by useful processes, such as authentication and authorization.
Authentication consists of recognizing the identity of users and the source of assets. It is essential for authorization: to authorize someone we need to know who they are. It is also important that a subject who performed some actions while being authenticated cannot deny performing them at a later time, which is called non-repudiation.
Even authorized actions, performed by subjects who are apparently authenticated, could be security violations, because there might be vulnerabilities in authentication controls. For this reason, all authentication processes should be logged by auditing.
- selection of dangerous actions to control;
- protection of log files;
- authentication, again, to link dangerous actions to the subject who performed them.
So, what do you need to do to ensure your app is secure? Well, you cannot be 100% sure that your app has no vulnerabilities. Just by installing it on an operating system, you inherit the vulnerabilities exposed in that operating system.
But you can minimize the number of security issues by following security policies.
Security policies are defined by you and your team, and their job is to remind you of possible vulnerabilities by providing you a way to avoid them.
They define rules regarding:
- actions that can be performed on some assets, and the users who are allowed to perform those actions;
- which users can access which data;
- which users have special privileges, and what those privileges allow them to do.
To defined security policies we need to
- determine what assets we want to protect;
- learn how the asset works and interacts with other things;
- determine how our asset's value is reduced directly or indirectly.
The value of the asset is also important in defining how to protect it. You do not want to spend $10k on security measures to protect an asset with a value of $10.
Security principles aid in selecting and designing the correct mechanisms to implement your goals.
Keep it simple
Do not overcomplicate your app design. Each level of complication will add multiple levels of security mechanisms needed to avoid vulnerabilities.
If you add (many) libraries to your app, you need to:
- regularly scan for known vulnerabilities in the library code, if you have access to it, to avoid vulnerabilities in the library;
- test (or trust) the vendor code, if you do not have access to it;
- apply your policies when integrating the library in your app.
If you use containers you need to know how to properly secure them. Many container's images are meant for development and thus are not secure for production. Remember that many tutorials online leave the system with vulnerabilities, because the author wants to make the tutorial simple.
If your app architecture is hard to decouple, it will be difficult to identify security vulnerabilities. If, on the other hand, it is simple, you can concentrate on one small part at a time to identify, control, and fix them.
If the system fails, make sure that it will default to a safe state. Do not log errors that could give information an attacker could use.
If an admin login request fails, do not assume the requester is a normal user, check their authenticated identity again, against a non-admin account.
If your app fails to retrieve payment data, do not default to the paid version, but show an error interface.
Each action in your app against an API should be verified for authentication and authorization. Do not assume that the user is always authenticated after login.
For instance, let's say that I let users download some books from my server after they logged in successfully in my app, but without authenticating them again on the download request. Then an attacker can recognize that request by just investigating the network traffic and download the books by repeating that request, from outside the app, without the need to be authenticated.
Do not rely on obscurity
Do not "secure" your app by using unknown algorithms to hide your data, and do not just obscure the algorithms that you use to encrypt your data. Once your app is installed on a user device. the code can be extracted and studied.
Use different levels of users for different tasks. This is also important in your team, not only in your app.
Karen from marketing does not need to have access to the source code.
When you perform a task, you should use an account that has the minimum necessary privileges to perform that task. Do not use a single admin account all the time.
If that account is compromised, all the data it has access to is compromised.
Security and psychology
Security is rarely appreciated by the users. The majority of users know nothing about security, still, they are those who need it the most. There are conflictsbetween security and the simplicity of usage of software.
Adding security will increase computing usage, change the routine for existing users, and maintaining security will cost more.
But you should not make security difficult for your users. Otherwise, they will find a way to work around it.
For instance, if you require users to change their password every month, they will start using the same password every month, only changing the final character:
If possible, design your security such that the tools an attacker needs to break it are more valuable than the asset. For instance, if an attacker needs to run expensive gear for days to break your security measures and access an asset with a value of $1k, then it might be more profitable for them to mine Bitcoins instead.
Log all authentication requests and all actions that need an authenticated user to be performed, for two main reasons:
- Given an action, for instance, the deletion of a file, you can always trace it back to the user who performed it;
- If an account is compromised, you can trace all the actions taken by that account to verify what data has been possibly exposed.
Defense in depth
Design your security mechanisms so that multiple, redundant measures are in place.
This way, if one of them fails, there will be other mechanisms still in place to protect your assets.
Single point of failure
Avoid placing all your assets in the same place. A single attack can compromise all of them at the same time. For instance, if you have a single DB with all the information of your app, then once that is compromised, all data is compromised.
Subscribe to a curated newsletter
Receive an email every week with curated content about Dart and Flutter.