Over a million developers have joined DZone.

Secure Design Principles: IEEE Report

DZone's Guide to

Secure Design Principles: IEEE Report

Christopher Lamb presents the 10 security design flaws from an IEEE report that was a collaboration between industry and academia.

Free Resource

Evolve your approach to Application Performance Monitoring by adopting five best practices that are outlined and explored in this e-book, brought to you in partnership with BMC.

Finally, in 2014, the IEEE released a report on Avoiding the Top 10 Software Security Design Flaws. This paper is the product of collaboration between industry and academia, and was released late in the year. As opposed to much guidance in industry today that addresses implementation, this report contains advice for system designers on how to design security into systems. Furthermore, while many papers describing principles trace their legacy back to the original Saltzer paper of 1975, this collection of design points is more independent, though doubtlessly still influenced to some extent.

Never Assume Trust

Engineers must always understand and examine trust assumptions in systems they design. They often make decisions about what parts of a system are trustworthy and commonly extend trust to an entire system under design without closely examining this assumption. They also will implicitly trust the state in a sequence of API calls without examining the implications of that trust. These both lead to excessive exposure, though in different dimensions. The first leads to situations where designers may store sensitive information in systems that cannot be secured or monitored, while the second leads to implicit state machines where states can be entered without appropriate authentication or authorization. The infamous Heartbleed SSL bug, for example, took advantage of previous authentication and context to insert spurious commands lowering the overall strength of encryption in the connection.

Trustworthy Authentication

Systems must implement strong authentication to ensure user identity. These systems must provide complete resource coverage as well, and must provide end-to-end protection. A common authentication pattern is to provide a ticket to a user after successful authentication. Here, the ticket must provide strong inherent resistance to cloning or malicious external generation. A poor ticket would be a base64 encoded username; this is easily created by external users and can then be used to access internal resources. A better ticket could be a salted hash based on a username, a time and time window, and a system key. Furthermore, system resources must always be protected behind some kind of verification. Using esoteric URLs which include long query strings will not protect resources from malicious access. The only appropriate protection is strong authentication and authorization.

Authorize After Authentication

Users or other agents must always be authorized after authentication. While a user's identity may be essentially constant, what that user is allowed to do is much more dynamic. In order to manage this, systems must check user authorization frequently, generally prior to any system action. This check need not be extensive—in most cases a simple check of a trusted repository for user role membership can suffice. Not checking authorization prior to action can lead to sensitive information leakage over time.

Separate Data and Control

Mixing data and control traffic can lead to command injection problems. Typical examples of this are SQL or shell code injection attacks where attackers submit control statements in what designers expect to be data elements. In SQL injection attacks, the typical initial injection vector is data submitted via a POST or GET to a web service. The web service then uses the submitted data in a SQL statement and submits it to a relational database backend, inadvertently executing the submitted SQL code. Other examples of this problem arise in computing languages that support dynamic command evaluation via {\em eval} statements or reflection. These language runtime attributes, though powerful, can be exploited similarly.

Validate Information

Both control statements and submitted data must be validated upon receipt. This helps ameliorate emerging problems with invalid control submission or deliberate corrupt data delivery, both problems commonly used by malicious attackers to attempt to compromise systems. These issues typically arise in systems over time as well, as developers and designers add new components to existing systems. Possible techniques to minimize the risk of these problems include centralized validation systems and conversion of submitted data to an accepted canonical form. These approaches make these services more widely available with a system, more visible, and more likely to be used.

Encrypt Correctly

Cryptography is a powerful data protection tool that can be easy to misapply. When not correctly used, cryptography provides only the illusion of confidentiality. Typical errors designers commit with cryptography include using homegrown cryptography algorithms, using the wrong algorithm for a particular problem, making poor choices with initialization information, mismanaging keys, and having underlying randomization services that are not random. Like validation primitives, encryption requirements tend to be abandoned as systems evolve without clear services and requirements, so encryption systems should be visible and support system evolution. Generally, encryption needs to be handled by experts.

Manage Sensitive Data

Sensitive information can leak from systems because either it is not correctly identified or it is not appropriately protected. In order to protect sensitive data, designers must first identify it, along with any particular regulatory protection requirements. Specific types of information with mandated protections include personal information of any kind, medical records, or financial information. Information must also be protected end-to-end, both at rest and in transit, to prevent any possible exploitation.

Consider Your Users

Users must be deeply considered in any system. Not only must they be provided with unobtrusive, easy-to-use security services with sensible defaults, but they must also be understood as possible attackers. Just as a user population's access and use habits must be clearly understood to provide controls that they will be willing to use, and use effectively, these same controls must correctly partition the application to protect the system as a whole from potential malicious insiders. The entire lifecycle of use should also be kept in mind, particularly from a data perspective. When user's delete accounts, for example, systems should remove any and all sensitive data to prevent future potential compromise.

Understand Attack Surfaces

A common modern attack vector is external supply chain systems. For example, Target, in 2013, was initially compromised via an external heating systems contractor. Designers need to understand exactly how external systems can provide new attack vectors. This includes things like third-party libraries, software developed by different teams, commercial components, and dynamically-loaded components as well as external partners and exposed APIs. New software will always change the threat profile and attack surface of a system. In order to mitigate this risk, new software must be clearly understood to that those affects can be identified. Once identified and analyzed, designers can determine if the risk of using the new components or exposing the new APIs is warranted.

Embrace Change

Systems are going to evolve over time. Security systems must be designed to support that change. They must themselves be able to be updated and they must support updating other components as well. Preferably, updates should be as small as possible, to both keep them from being corrupted and attacked as well as to make update monitoring easier. The security system should also be able to triage specific parts of a system when needed to contain compromise if and when they occur for both internal components and external systems. Designers must pay close attention to key management and secret control as well. Keys and secrets need to be changed regularly, and systems should be designed to support this regular rotation without any data loss or inconvenience to users.

Learn tips and best practices for optimizing your capacity management strategy with the Market Guide for Capacity Management, brought to you in partnership with BMC.

design ,principles ,performance

Opinions expressed by DZone contributors are their own.


Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}