This article was originally published in the December Issue of (In)Secure Magazine.
Most application developers are familiar with the directive “Build security in from the start.” They’ve heard it and read it numerous times during debates about application security. However, there is not a whole lot of information on what it actually means. Aside from the lack of information about what exactly is meant by the term security, there is also a lack of information about when it is specifically NOT a good idea to build it in from the start.
This article will attempt to clarify this topic by laying out the aspects of security that need to be covered by application developers, and by specifying at which point in the application lifecycle they should occur.
Identity Management and Access Control
One of the first tasks to start working on is designing the integration with your identity management system. If you are developing an application that is used solely by your company’s employees, you will most likely be integrating with the identity management system that your company already uses. In that case, you need to determine the roles of the various users of your application.
Your application may have only one role (user) which would certainly make your life simple. Most likely, though, there will be different roles for different users, giving them access to different parts of the application. You will need to understand the roles that are managed by your identity management system, so that you can know whether you can use existing roles or whether new ones need to be created.
You will then need to integrate this with your access control system. Different roles will have different capabilities in the application and the access control system needs to be set up to enforce those rules. Another interaction with the identity management system that needs to be understood is the creation and deletion of users.
In some applications, both actions are performed completely outside of the application. Most internal applications are this way. The creation and deletion of users is handled by workflows in the identity management system and the application does not play any part in that process.
On the other hand, applications whose user population is composed of the general Internet population must have some method for creating and deleting users. In these instances, many organizations choose to delegate identity management to a third party like Facebook or Google. If handled strictly according to the third-party protocols, this can be a valid solution from a security standpoint, although it drags along some business issues that may or may not be acceptable to your stakeholders. Note that a solution like this does not address the need for access control or session management.
Your access control system will manage sessions for you, but it is your responsibility to determine how you want to handle user sessions in the event of a server failure. The implementation will vary depending on your access control system and your web container, but you will still need to find a solution that implements the right balance of user (in)convenience and a possibly costly failover solution.
Encryption and Data Management
Every piece of data that passes through your system must be identified and you must determine what level of protection the data requires. This is done through a data classification process. I will assume that you are not handling credit card data, as that requires more advanced protection techniques that are beyond the scope of this article.
When your data classification is complete, you will know which of the data you are handling requires encryption during transit and at rest.
Each piece of data that requires encryption will need to be encrypted through the entire system, not just from the browser to the frontend servers. That will require using an encrypted transmission protocol when the data is transferred between servers, and using encryption whenever the data is stored. Doing this early in a project is important so that you can get your DevOps or data center support team involved. They will be the ones who implement the transport layer encryption, the certificate management, and the key management. Some of the things they need to set up may take some time so it’s critical to get them involved early on.
If you mean to implement encryption in your application, your next and absolutely most important task will be to determine your strategy for secure key storage. If your environment already supports encryption you will most likely be able to make use of your existing key storage mechanism. If not, you will need to come up with one. While there are key management systems you can purchase, you can also “roll” your own.
If you choose the latter option, you should, at a minimum, follow these guidelines:
1. Do not store keys with the data they protect.
2. Create a secure location to store the keys.
Another critical part of your key management is to have a method for rotating the keys. First you will need to determine an appropriate expiration period (all keys have expiration dates). Pick one that is appropriate for your organization and the data you are protecting. Next, determine the process you will use to rotate your keys.
Ideally, you want a process that will be completely innocuous to your application. This is especially true if you are developing an application that will have zero downtime. You wouldn’t want to have to take your high-traffic website offline just to rotate the keys.
This topic could use an entire book, but the key points to keep in mind when architecting your system is that:
1. All incoming connections to the server must be assumed to be potentially hostile, even if they have a valid session.
2. All client environments are completely insecure at all levels.
3. All networks outside your private-network perimeter are completely insecure. Your server-side code has to be written as if it is under attack from authenticated, in-session hostile code, and your client-side code has to assume that every byte of code from every server response can be examined and subverted by expert hackers.
Logging is going to be covered later in this article, but during this design phase make sure that you are able to track transactions end-to-end through the system. This will help you identify when an attacker has figured out how to inject a transaction at a point downstream from where a transaction should be initiated.
At this point, we’ve covered all the security-related items that must be built in up front. The remaining items are things that can wait until later in the project. In some cases, they can’t be initiated until the project is well under way, and in other cases they are activities that must be done continually throughout the life cycle of your application.
You won’t be doing vulnerability scanning up front but you will need to start scanning after you get some code running. You don’t want to wait until you are ready to move to production to start scanning. You might be overwhelmed with the number of vulnerabilities. If you start scanning your code early in the project you will be able to keep the number of vulnerabilities that need to be fixed to a manageable level.
You might also uncover some bad habits of some developers that can be fixed, or some vulnerabilities in your platform or libraries that need to be patched.
What is your strategy for verifying that the external libraries that you have downloaded from the Internet are not “bad”? Security experts are divided on the true risk of cross-build injection attacks, but you still need some way to determine that your external libraries do not contain malicious code. On the server-side, this generally means relying on widely used libraries, and closely controlling the library sources and versions.
For browser-based dependencies, this should be less of an issue because all client-side code should be regarded as potentially compromised.
Make sure that you are not writing any sensitive information into your logs. You don’t want your log files to be an easy way for attackers to obtain this data.
You might be tempted to continue providing the ability to log sensitive information at debug level, as this can come in handy when you are dealing with an incident in production. But you have to have strategy for scrubbing sensitive data from logs.
There’s not much you can do to defend against a denial of service attack at the application layer. However, you can put some effort into finding ways to prevent attackers from wasting resources. For example, you can use a CAPTCHA to prevent illegal account creation, or think of ways to prevent attackers from sending simple requests that consume database connections or other resources.
The security-related tasks that must be completed during application development have been listed above. Your application may not need all of them, but depending on what you need, you now know which tasks need to be performed up front.
Have any more questions about data security? Don’t hesitate to contact us or leave a comment below. To read more in the future, don’t forget to follow us on Twitter by clicking below: