3 Essential Elements to Creating Highly Secure Applications for an Insecure Ecosystem
Guest post by Kos Semonski, Principal Technology Security – AT&T Chief Security Organization
Computer security is often shrouded in mystery and secrecy. But the reality is that computer security is built on very basic and logical foundations. This is shown in the CIA Triad, a conceptual model that outlines the core aspects of computer security and provides a baseline for evaluating and applying security controls.
The three elements of the triad are:
- Confidentiality: Ensuring that data is accessed only by authorized individuals.
- Integrity: Ensuring the data is not modified by unauthorized individuals.
- Availability: Ensuring the data is available when needed.
Foundationally, all security controls are expressions of the CIA Triad (Fig. 1)
Fig. 1 illustrates the interdependency of the CIA elements for Information Security.
From a pure security aspect, it is a fundamental requirement to consider all three properties of the triad; however, it is most important to concentrate on the Confidentiality attributes when considering mobile application development. This is not to say that Integrity and Availability are not of concern to application developers, but rather that these security attributes tend to be managed at different levels of the Eco-system (e.g., Operating System & Network / Connectivity).
In addition to the CIA triad, mobile application developers must consider the three natural states of data: storage, transit, and processing. In other words, the data housed within applications can be latent or saved to files on a device (STORAGE), on the move being transmitted across the network or shared with other programs (TRANSIT), or in an active state within the program and available to the processor (PROCESSING).
The chart below illustrates the interdependency of these attributes. (Fig. 2)
Fig. 2 illustrates the interdependency of the CIA elements in relation to natural data states.
Developers have the distinct ability to ensure the confidentiality of a program’s data in storage, transit, and processing. They do so by using encryption technologies and employing good housekeeping policies. The grid below shows the focus for a developer on the Confidentiality aspects of our data states. (Fig. 3)
Fig. 3 illustrates the interdependency of the Confidentiality element in relation to natural data states.
With this reduction of requirements developers have a more achievable goal because programming should, at minimum, ensure the Confidentiality of our data when it is Processed, Stored, or Transmitted. Pretty simple, eh? Well, sorta’……
All of this is accomplished by making sure that applications are coded with care. If developers approach program designs with security in mind, these security attributes should naturally occur without (too much) added coding or difficulty. Some basic considerations include the following:
- Programs should leverage publically-available encryption binaries or libraries when caching, storing or transmitting sensitive information and/or variables.
- Programs should use only secured network resources for data transfers (e.g,. TLS v1.2).
- Programming loops and decision trees should account for ALL possibilities.
1) Leveraging Publically Available Encryption
At a minimum, developers should be encrypting user login credentials in the transport and storage state. Also, please note, there will be many other examples to incorporate encryption of data besides login credentials. For more information and guidance regarding what and when to encrypt, see the following article and use good judgment. (Personally Identifiable Information)
Use Modern / Audited Encryption Binaries And Libraries
One of the easiest things we can do is to use encryption algorithms that are modern and recommended by the security community at large as best practices. For instance, just a few years ago the algorithms and protocols of MD5 and SHA1 were considered sufficient; however, that is not necessarily the case now. As developers, we should set our sights on leveraging AES256 for encryption and SHA256 for hashing where possible.
If you do not have a professional Cryptographer on staff, consider using audited binaries for your program’s encryption routines. In other words, don’t attempt to create your own encryption routines. Instead, leverage proven binaries like bcrypt and GPG, and/or use audited libraries like cryptlib. There is safety in numbers, and these publically available resources have stood the test of time.
Below are a couple of articles illustrating the potential impacts of unencrypted data compromise.
2) Secure Your Network Transfers
We recommend using secured network resources whenever possible. Use TLS (HTTPS) vs. open channels when selecting server platforms for your application resources. By ensuring that your program REQUIRES encrypted channels, you provide another layer of assurance for your users EVEN IF they decide to connect using Open Wi-Fi hot-spots. There is already significant acceptance and movement to a fully encrypted Internet, so it is better to do it now instead of trying to go back and remediate the vulnerabilities. More information on these protocols can be found here. (SSL/ TLS Security 2015 – A Simplified Quick Guide)
A common exploit of unsecured network transfers is referred to as “Man In The Middle.” Below are a couple of articles illustrating the potential impacts of this using unencrypted (or weakly encrypted) communication channels.
3) Controlling All Program Flow and Branching
Finally, map out and control the variables you use in your program. Be sure to add consideration for UNEXPECTED inputs from users. Most people only concentrate on the “expected” responses from users or processing results, but a good program should always have deliberate considerations for the entire range of the variable’s domain. It is basic error trapping…. but for whatever reason, it tends to elude many programmers.
Fig. 4 illustrates the continuum of potential user input to program variables.
Programming with a security focus is easily accomplished by getting in the habit of programming DEFAULT handlers within CASE and SWITCH statements, and by analyzing inputs to ensure that ONLY “expected” syntax is allowed. Also, ALWAYS understand where your program will branch when considering decision trees and method, function, or subroutine logic. Programs can do very unpredictable things when unexpected data is assigned to program variables. SQL injection attacks are a great illustration of the dangers of improper variable handling.
Always avoid storing any data elements, or store the minimum amount possible, on devices. Sometimes, this is easier said than done, so if you have to store data elements, be sure to encrypt or hash the data rather than storing it in clear text form. Be sure to delete unneeded data artifacts and cache files on program exit, and consider adding variable cleansing statements that null out or otherwise clear out variables after the data they hold is no longer needed. In other words, just do a little house keeping.
As programmers, we can significantly enhance the security quotient of our applications by simply leveraging good programming practices, requiring encryption for stored or transmitted data, and by cleaning up after ourselves. With a little bit of diligence, we can have a measurable positive impact on the security of our user’s data. (2015 Data Breaches Reports)