Developing secure and reliable cloud web applications is not an easy task. Even - very difficult. If you think that this is not so, then either you are a representative of an unknown science of a higher form of life, or - wait for a hefty roasted rooster.
If you are inspired by the ideas of creating a minimum viable product and are confident that you can develop something useful and safe for a month, think twice before putting into practice such a “product”, but rather only a prototype.
')
After you review the following checklist of tasks that need to be solved to ensure the security of a web project, you will surely see for yourself that much of what is in it is not taken into account in your design. What to do? At a minimum - be honest with potential users and inform them that your project is still under development, that you offer them to become familiar with the prototype, which has not yet implemented a complete security system.
Database
If possible, use encryption to store information that identifies the user, and to store sensitive data, such as access tokens, email addresses or payment details (this approach, in particular, will allow you to limit queries to the database to the exact match level).
If your DBMS supports cost-effective encryption of stored data, turn it on to protect the information stored on the disks. In addition, make sure that all backup copies of the databases are also encrypted.
Use user accounts with minimal privileges to access databases. Do not use the superuser account and check the system for unused accounts and accounts with too weak passwords.
Store and transfer account data, system access tokens, and other secret information using a key vault designed for similar work scenarios. Do not store such data, rigidly specifying them in the application code.
Protect the system from SQL injection attacks using only prepared SQL queries. For example, if your project is designed for Node.js, do not use the mysql nmp library, refer to the mysql2 library, which supports prepared queries.
Development
Ensure that system components are checked for vulnerabilities before each release. We are talking about all the libraries, packages, working environment. Ideally, checks should be automated within the CI-CD process.
Secure the security of the developer’s computers by addressing this issue with the same attention that you take to the security of production servers. Development should be conducted on protected, isolated from a potentially dangerous external environment machines.
Authentication
Make sure that all passwords are hashed using a suitable cryptographic algorithm like bcrypt . Do not use samopisnyh hashing functions, correctly initialize the used cryptosystems with the help of high-quality random data.
Use time-tested, well-proven components to organize logging in, recover your forgotten password, and reset your password. Do not reinvent the wheel. The fact is that in self-development you will find it very difficult to ensure the correct operation of such mechanisms in all possible scenarios.
Implement simple, but not system-threatening, password requirements that encourage users to create long passwords consisting of random character sets.
Use multifactor authentication for all service providers.
DOS attack protection
Make sure that DOS-attacks on your API will not affect the performance of the site. At a minimum, enable frequency limit requests in the slowest API paths and in those parts of the project that are associated with authentication. For example, we can talk about the modules of entry into the system and the subsystems to create access tokens. Consider using CAPTCHA in parts of the project that are accessible from the outside world to protect server subsystems from DOS attacks.
Set sensible limits on the size and structure of the data that users can send to the system, as well as on the queries they perform.
Consider using a system to mitigate the effects of distributed DOS attacks, for example, using a global caching proxy service like CloudFlare . During an attack, this will help your project survive, and in normal times it will reduce the load on the servers and speed up the loading of the site.
Web traffic
Use TLS for the entire site, not just to protect the authorization system. Never use TLS to protect an authorization form only. During the transition period, enable the strict-transport-security HTTP header to force the use of the HTTPS protocol.
Cookies must have the httpOnly attribute, they must be secure, among their attributes must be the path and domain parameters.
Use Content Security Policy ( CSP ) without giving unsafe-inline and unsafe-eval permissions. This policy is not easy to set up, but it is worth the effort and time spent. Use the Subresource Integrity mechanism for CDN content.
Use the X-Frame-Option and X-XSS-Protection HTTP headers in client responses.
Use the HSTS mechanism to provide access to the system using TLS only. Do not trust client systems, ensure the use of HTTPS on the server side.
Use CSRF tokens in all forms, use the new SameSite cookie attribute to protect against CSRF attacks. It is supported by modern versions of browsers.
API
Check that there are no resources in the public API that can be discovered by brute force.
Users must be fully authenticated and properly authorized before they can use the API.
Validation and data conversion
Check, on the client side, the data entered by users. This will allow them to quickly get a response to their actions. However, never trust this check. Always check and convert to the format you need what the user entered before displaying on the pages of the site.
Check everything that comes from the user, using the white lists on the server. Never insert unencoded user-entered data into HTTP requests and responses. Under no circumstances use potentially dangerous data entered by the user in SQL queries or in other server logic.
Cloud Settings
Check that all cloud services have a minimum number of ports open. Although security through information hiding is not a defense, using non-standard ports will make life more difficult for those who try to attack your system.
Keep databases and services in virtual private clouds (Virtual Private Cloud), which are not accessible from the outside. Be very careful when configuring AWS security groups and setting up peering between VPCs, as errors can lead to internal services being visible from the outside.
Isolate logical services in different VPCs and set up peering between them to provide inter-service communication.
Make sure that all services accept data only from the minimum necessary set of IP addresses.
Restrict outgoing traffic by IP addresses and ports to minimize the possibility of targeted cyber attacks and bot attacks.
Always use AWS IAM roles, not a superuser account.
Use minimal access privileges for those involved in system maintenance and for developers.
Regularly, according to the schedule, perform the rotation of passwords and access keys.
Infrastructure
Make sure you can upgrade your project without downtime. Implement a fully automatic system that allows you to quickly update software.
Build your entire infrastructure using tools like Terraform, rather than through the management console for cloud services. Strive to implement the infrastructure-as-code approach. This will allow you, if necessary, to recreate everything with literally one keystroke. Do not allow the manual creation of cloud resources. Audit configuration.
Use centralized logging tools for all services. The logging system should be built so that you never need to connect to the system via SSH only to view or download logs.
Do not connect to services via SSH, except for occasional cases of their diagnosis. Regular use of SSH usually means that your important tasks are not automated.
Do not keep port 22 constantly open in any AWS group. If you absolutely need SSH access, use only public key authentication, not logins and passwords.
Give preference to immune hosts rather than long-lived servers that you patch and update. Here is useful material on this topic.
Disable unused services and servers. The most secure server is the one from which the power cord was pulled.
System testing
Audit the architecture and implementation of the system.
Perform penetration testing - hack yourself. However, it is useful to involve third-party specialists in such tests.
Training
Educate staff (especially newbies) about cyber risks and social engineering techniques used to hack systems.
Contingency plan
Create a threat model that describes what you are protecting against. It should list, with prioritization, possible threats and attack participants.
Prepare a clear contingency plan. One day you will need it.
Results
The checklist considered in this material does not claim to be complete. The thing is that each web project is unique and only its creators know exactly what threatens it, and how to deal with these threats. However, various projects have many similarities. Therefore, we believe that everyone will be able to fine-tune the list presented here for his project.
What you read is based on more than fourteen years of experience of the author of the material in the development of secure web applications. This experience was not easy for him, and we are confident that his findings will make life easier for those who are concerned about the security of their web solutions. Dear readers! And what would you add to this list?