Secure Software Development Principles
Join the DZone community and get the full member experience.Join For Free
There is growing evidence that criminals, terrorists, and other malicious actors view vulnerabilities in software systems as a tool to reach their goals. Today, software vulnerabilities are discovered at a higher rate than ever. These vulnerabilities are caused by software designs and implementations that do not adequately protect systems and by the development practices that do not focus sufficiently on eliminating implementation defects that result in security flaws.
There is little evidence of improvement in the security of most of the products; many software developers do not understand the lessons learned about the causes of vulnerabilities or apply adequate mitigation techniques. This is evidenced by the fact that CERT(Computer Emergency Readiness Team) continues to find the same types of vulnerabilities in newer versions of the products that we saw in the earlier versions.
Secure Software Development Principles
The goal of this article is to discuss in detail Secure Software Development Principles, which if adopted and practiced, can help mitigate the vulnerabilities in the software system we design and develop. Some of the earliest principles were proposed by Saltzer in 1974. These eight principles apply today as well and they are as follows:
Economy of Mechanism
This is a widely known principle that applies to all aspects of a system, and software design and is particularly relevant to security. Security mechanisms should be small and simple so that they can be easily implemented and verified. An example is Security Kernel.
Complex designs increase the likelihood that errors will be made in their implementation, configuration, and use. Additionally, the effort required to achieve an appropriate level of assurance increases dramatically, as security mechanisms become more complex. As a result, it is generally more cost effective to spend more effort in the design of the system to achieve a simple solution to the problem.
Basing access decisions on permission rather than exclusion means that, by default, the access is denied and the protection scheme identifies conditions under which access is permitted. If the security mechanism fails to grant access, this situation can be easily detected and corrected. However, a failure to block access may fail by allowing access - which may go unnoticed in normal use. Black Listing and White listing data sensitization techniques fall under this category.
Complete Mediation: Every access to every object must be checked for authority. The figure below illustrates the concept:
This principle requires that access to every object must be checked for authority. It also requires that the source of every request is positively identified and authorized to access a resource. Whenever a subject attempts to read an object, the operating system should mediate the action.
First, it determines if the subject is allowed to read the object. If so, it provides the resources for the read to occur. If the subject tries to read the object again, the system should check that the subject is still allowed to read the object. Most systems would not make the second check. They would cache the results of the first check and base the second access on the cached results.
A software design is not secured by hiding it from potential attackers or obscurity of code. The design should not be a secret. Encryption systems and access control mechanisms should be able to stand the open review and still be secure. We can achieve this by decoupling of the protection mechanism from protection keys or passwords.
This approach brings the added advantage of permitting a thorough examination of the mechanism without concern that reviewers can compromise the safeguards. Implementing an open design also allows users to verify that the protection scheme is adequate for a particular application.
Separation of Privilege
Where possible, a protection mechanism that requires two keys to unlock it is more robust and flexible than one that allows access to the presenter of only a single key. Separation of privilege eliminates a single point of failure by requiring more that one condition to grant permissions. A widely popular example is "Two Factor Authentication" which is based on "something you have" and "something you know".
Every program and every user of the system should operate using the least set of privileges necessary to complete the job. This approach reduces the opportunities an attacker has to execute arbitrary code with elevated privileges. We can implement this principle in the following ways:
- Grant each system, subsystem, and component the fewest privileges with which it can operate.
- Acquire and discard privileges in such a way that at any given point, the system only has the privileges it needs for the task in which it is engaged.
- Discard the privilege to change privileges if no further changes are required.
- Design programs to use privileges early, ideally before interacting with a potential adversary (e.g. a user), and then discard them for the remainder of the program.
Least Common Mechanism
This principle, in some way, conflicts with overall trends in the distributed computing and dictates mechanisms common to more than one user should be minimized because these mechanisms represent potential security risks. If a rogue user manages to breach the security of one of these shared mechanisms, the attacker may be able to access or modify data from other users, possibly introducing malicious code into processes that depend on the resource. In order to avoid these scenarios, consider designing your system so that the mechanism executes in the process space of your program and is not shared with other applications.
It is essential that the human interface be designed for ease of use, so that users routinely and automatically apply the protection mechanisms correctly. The modern term for this principle is "usability". Usability is also a form of security because user errors can often lead to security breaches — an example would be setting or changing access controls. Many of the vulnerabilities in the US CERT Vulnerabilities Database can be attributed to usability problems. Other common usability issues at the root cause of vulnerabilities cataloged in the database include:
- The program is hard to configure safely or is easy to misconfigure.
- Installation of procedure creates vulnerability in other programs.
- Configuration problems.
- Confusing error and confirmation messages.
Usability problems in the documentation can also lead to real-world vulnerabilities including insecure examples or insecure descriptions. Overall, there are many good reasons to develop usable systems and perform usability testing and Security happens to be one of these reasons.
Software development practices that are meant to reduce or eliminate vulnerabilities in system development must be process agnostic, that is capable of being integrated into a broad variety of existing processes. While principles alone are insufficient for secure software development, principles can help guide secure development practices.
Opinions expressed by DZone contributors are their own.