At Red Hat, we recognize the importance of implementing security measures early in the software development life cycle (SDLC), as breaches are becoming more pervasive in today's society. Our work in Red Hat Product Security is to help minimize the software-based risks of enterprise open source from Red Hat, while affording the many benefits that open source can provide.
Security by design
Red Hat invests significantly in the maintenance of open source software throughout the life of every product. For supported software we ship, we take on the responsibility of not just supporting it but also addressing issues of significant concern, such as security. Introduced in 2021, a new category in the Open Web Application Security Project (OWASP) Top 10, Insecure Design, focuses on risks related to design and architectural flaws, with a call for more use of threat modeling, secure design patterns and reference architectures. This shift-left approach to introduce security checks and work during the early development and release management phases is inherent to being successful in the work that we do in Red Hat.
As no complete checklist exists that system designers/developers or security architects can follow to guarantee that products are secure, at Red Hat we endeavor to understand the threat or risk to a product and as part of that we follow a set of widely applicable security design principles during our threat modeling process, which are intended to help improve the security of the networks and technologies that underpin Red Hat products.
In this post, we’ll talk about key security principles that will work in any kind of application and that we use during the threat modeling process at Red Hat.
Security principles and threat modeling
These principles are inspired by the OWASP Development Guide and are a set of desirable properties, behavior, design and implementation practices that we take into consideration when threat modeling at Red Hat.
- Principle: Defense in depth
- Principle: Secure by default
- Principle: Least privilege
- Principle: Separation of duties
- Principle: Minimize attack surface
- Principle: Complete mediation
- Principle: Open design
- Principle: Isolated compartments
- Principle: Evidence production
- Principle: Application coding best practices
Principle: Defense in depth
Security should be viewed holistically and, wherever possible, multiple levels of security controls should be used. At Red Hat we do not dismiss the usefulness of a mitigation or protection on the grounds that "it does not fully resolve the issue," rather we strive to implement a set of overlapping protections to reduce the risk using end-to-end controls.
- Build defenses in multiple layers that back each other up, forcing attackers to defeat independent layers, thereby avoiding single points of failure.
- As a design assumption, expect some defenses to fail on their own due to errors, and that attackers will defeat others more easily than anticipated or entirely bypass them.
- Execution of defense in depth must be balanced with complexity, manageability, performance and the cost of the overall implementation.
- Expenditures of capital and resources should never eclipse the cost of the asset or expected loss if compromised.
Example of threat model finding: Not encrypting traffic to a Relational Database Service (RDS).
- CWE-319: Cleartext Transmission of Sensitive Information
- CWE-654: Reliance on a Single Factor in a Security Decision
Principle: Secure by default
Use safe default settings.
- For access control, deny by default. Systems should be configured in a least privilege model, so that no unnecessary services/daemons or accounts are enabled.
- Design services to be fail-secure, meaning that when they fail, they fail “closed” (e.g., denying access).
- As a method, use explicit inclusion via allowlists (goodlists) of authorized entities with all others denied, rather than exclusion via denylists (badlists) that would allow all those unlisted.
Example threat model finding: No Network Policy in place on namespace in OpenShift Cluster.
Principle: Least privilege
Allocate the minimum privileges needed for a task, and for the shortest duration necessary. Using controls like privilege revocation or privilege dropping, where code explicitly drops privileges as soon as they are no longer needed.
- This principle is related to the military need-to-know principle—access to sensitive information is granted only if essential to carrying out one’s official duties.
- Limiting scope of access and permissions increases protection against fraud and user error.
- Limiting access and permissions helps reduce the scope of exposure and can help contain the damage a single person or entity can do.
- Systems and processes should be designed so that access and permissions are limited.
- Roles should be reviewed, agreed upon and regularly audited by business personnel.
Example threat model finding: Operator uses wildcards when defining resources, verbs or API groups in Role or ClusterRole. Refer to Kubernetes Operators: good security practices.
Principle: Separation of duties
An example of how we use practices like privilege separation at Red Hat, we divide a service's functionality among a set of communicating processes so that one process does network-related operations but passes validated requests to another process that has access to the resources needed to carry out those operations. In this case, it is more difficult for an exploit to the first process to reach the resources needed to impact the service, because those are accessible only to the second process.
- No one person or entity should have control of or access to all elements of a process or system.
- Separation of Duties (SoD) helps enforce accountability and helps prevent individuals from circumventing internal controls.
- Processes and systems should be designed so that multiple parties are required for completion, especially those dealing with monetary transactions or those that require handling sensitive information.
Example threat model finding: The same service account is being used instead of separate dedicated ones. Refer to OWASP - Access Control.
- Insufficient Granularity of Access Control
- CWE CATEGORY: Privilege Separation and Access Control Issues
Principle: Minimize attack surface
Every interface that accepts external input or exposes programmatic functionality provides an entry point for an attacker to change or acquire a program control path (e.g., install code or inject commands for execution), or alter data that might do likewise.
- Keep designs as simple and small as possible (KISS Principle). Reduce the number of components used, retaining only those that are essential.
- Minimize functionality, favor minimal installs and disable unused functionality.
- Economy and frugality in design—especially for core security mechanisms—simplifies analysis and reduces errors and oversights.
- Configure initial deployments to have non-essential services and applications disabled by default.
Example threat model finding: Operator is deployed and Pod is running but not being used at present. Refer to Kubernetes Operators: good security practices
- CWE-561: Dead Code
- CWE-637: Unnecessary Complexity in Protection Mechanism (Not Using 'Economy of Mechanism')
Principle: Complete mediation
- For each access to every object, and ideally immediately before the access is granted, verify proper authority.
- Verifying authorization requires authentication (corroboration of an identity), checking that the associated principal is authorized and checking that the request has integrity. Here, integrity means that it must not be modified after being issued by the legitimate party. For example, verify that responses match requests in name resolution and other distributed protocols. Their design should include cryptographic integrity checks that bind steps to each other within a given transaction or protocol run to detect unrelated or substituted responses.
Example threat model finding: A component does not manage or enforce authorization e.g. via Access Control Lists (ACLs).
Principle: Open design
Do not rely on secret designs, attacker ignorance or security by obscurity. Invite and encourage open review and analysis.
- There should be sufficient security controls in place to keep your application safe without hiding core functionality or source code.
- Kerckhoffs’ principle—a system’s security should not rely on the secrecy of its design details.
Example threat model finding: The software contains a hard-coded password, which it uses for its own outbound communication to external components.
Principle: Isolated compartments
- Compartmentalize system components using strong isolation structures (containers) that manage or prevent cross-component communication, information leakage and control. This can help limit damage when failures occur and helps protect against escalation of privileges
- Restrict authorized cross-component communication to observable paths with defined interfaces to aid mediation, screening and use of chokepoints. Examples of containment include process and memory isolation, disk partitions, virtualization, software guards, zones, gateways and firewalls.
Example threat model finding: Network policies are in place but they allow access from unnecessary namespaces which increases the attack surface.
Principle: Evidence production
- Record system activities through event logs, monitoring tools and other means to promote accountability, help understand and recover from system failures, and support intrusion detection tools.
- Sufficient controls must be in place so that accountability can be enforced for users and systems and all actions recorded so that activity can not be denied.
Example threat model finding: Current logging is not sufficient—log events of interest as per infosec guidelines and those log files must be integrated with a centralized log collection and analysis platform.
Principle: Application coding best practices
- Following coding best practices helps reduce the cost of mitigating defects by catching problems earlier, provides a consistent set of tools and configurations to easily convey to the development community which should increase speed of delivery, and reduces the expected loss due to vulnerabilities since more are remediated prior to production release.
- Verify that all received data meets expected (assumed) properties or data types. If data input is expected, ensure that it cannot be processed as code by subsequent components if another data input is received.
- Industry best practices such as the OWASP and SANS “top 10” lists should be referenced and corrected during the software development life cycle.
Example threat model finding: Debug code left on a production server. This oversight during the "software process" allows attackers access to debug functionality.
If you want to learn more about the practice of threat modeling visit the Open Practice Library.