All software design choices drive security. It all impacts security.
Programming language selection, CRUD, DRY, SOLID principles, code complexity, and even something as seemingly trivial as variable naming, can influence software security. Furthermore, we’ll explore how architectural designs like Domain-Driven Design, micro services, and event-driven architecture contribute to or detract from a system’s overall security.
Programming Language Selection Each language comes with its security implications. For instance, languages like C and C++ offer great performance but are prone to memory management errors leading to vulnerabilities like buffer overflows. Languages like Java, may prevent those buffer overflow but they typically have their own issues. Java uses references to manage strings. This can lead to issues with sensitive data being in memory longer than intended. Each language has their advantages, and disadvantages. Being aware of them is imperative.
DRY (Don’t Repeat Yourself) The DRY principle leverages code reuse. While the obvious security implication is that repeating vulnerable code requires to be fixed twice. The not-so obvious reason is the leveraging existing code rather than recreating what can be complex code bases. The easiest example of this is encryption algorithms. These are complex algorithms which are very mathematically intensive.
SOLID Principles SOLID principles help create more maintainable, understandable, and flexible software. From a security standpoint, these principles, particularly the Single Responsibility and Open/Closed principles, help in segregating the system into well-defined modules. This segregation not only makes the system easier to manage but also limits the security vulnerabilities to specific areas, making them easier to identify and mitigate. They create internal trust boundaries for code and add to the layered approach of defense in depth.
Code Complexity Complex code is hard to understand, and what’s hard to understand is hard to secure. Complex code often leads to bugs, which can turn into vulnerabilities. Simplifying code, using well-known design patterns, and regular code reviews are essential practices. The less complex the code, the easier it is to spot and rectify potential security issues. Code is read way more often than it is written. There is no reason to show how few lines of code can be used to write a process when the compilers will almost always handle the efficiency themselves.
Variable Naming Variable naming might seem trivial, but clear and consistent naming conventions improve code readability and understandability. When code is understandable, it’s easier to spot anomalies that might indicate a security issue. Ambiguous variable names can lead to misunderstandings about how a piece of code functions, potentially leading to security vulnerabilities. The use of Integrated Development Environments (IDE) leverage code completion. Saving key strokes now, can lead to struggles later.
Domain-Driven Design (DDD) DDD focuses on modeling software to match a business domain. This approach can enhance security by aligning the software closely with business requirements, including security needs. This process can help identify where off the shelf components can be leveraged (authentication, for example).
Microservices Architecture Microservices architecture breaks down an application into smaller, independently deployable services, each running its process. From a security perspective, this can be both beneficial and challenging. On the one hand, it limits the scope of a security breach to a single service. On the other, it increases the overall attack surface as there are more services to secure. Ensuring robust security in a microservices architecture requires careful planning and implementation of security protocols at each service level.
Event-Driven Architecture In an event-driven architecture, the flow of the application is determined by events. This architecture can improve security responsiveness since the system can be designed to react to security-related events in real-time. It also introduces complexity in tracking the flow of data and understanding how different events impact the system, which can be a challenge from a security perspective. This architecture typically uses an event management system. This event system can store user data and can need to be protected and are directly impacted by privacy laws. Understanding the implication of a student wanting to have all their information deleted while also maintaining an audit history of the grades for that student can add complexity.
It is now time to build our educational system. By the time you are done reading this book you’ll understand why software security is hard, but it doesn’t need to be complex.