Software and System development is a complex and demanding activity undertaken by people with different skill levels and varying security awareness.
This can present a serious risk to organizations - security teams must understand these risks, balance them with business requirements and enforce appropriate mitigation mechanisms.
An in-house development team supports unique objectives in many organizations, tailored software is a competitive advantage and can ultimately decide on the success of a business.
Careless or even malicious development on the other hand can introduce vulnerabilities and backdoors to such software and leave the organization open to exploitation by malicious actors.
It’s, therefore, crucial to introduce controls and a structured process to the entire development process to protect against vulnerabilities.
This blog is the first in a series about security in software and system development.
Software Developers use programming languages to develop software. This chapter takes a look at the different types of languages and the security implications.
The instructions that a computer processes are a long series of binary digits in a language known as machine code. It’s a language of 0s and 1s and no human can understand anything but the simplest instructions without the assistance of specialized software.
Assembler is a higher-level language to represent the machine code. It’s still a complex and obscure way of programming and requires specific knowledge about the hardware it will interact with.
These languages are feature-rich and provide standards for common tasks, permit debugging, and maintain architectural agnosticism.
Compiled vs. Interpreted
When using a compiled language like C or Java, a tool known as a compiler converts the higher-level language into an executable file that is distributed and designed to be used on a specific operating system. It is not possible to directly view or modify the software instructions in such a compiled executable.
Reconstructing the source code from an executable with a decompiler is described with the term reverse engineering. This is useful for malware analysis or intelligence gathering, where access to the original source code is not available.
Compiled and interpreted languages both have advantages and disadvantages from a security perspective. Compiled code is less likely to be manipulated by a third party, but security flaws or backdoors in the source code are harder to detect since the original instructions can’t be accessed by the end-user.
Interpreted code on the other hand is very transparent because the end-user can read the code before executing it in an interpreter. The disadvantage is that everyone who touches the software can introduce malicious instructions.
OOP is a standard based on the concept of “objects” and focuses on the interaction of such objects rather than on a series of steps as seen in functional programming. Many modern programming languages (such as Java, Python, etc.) are multi-paradigm and support OOP.
Object-Oriented programming is generally speaking more reliable and reduces the propagation of errors in a system. From a security perspective, OOP is a black-box abstraction because users don’t need to know the inner working of an object but rather the details and abilities of the interface to an object.
The desired characteristic in OOP is the self-containment of an object or in other works the encapsulation. Below are some core concepts of object-oriented programming.
Message is commonly used in OOP to describe the input of an object.
Method this is the name for the instructions (or code) of an object. It specifies the actions in response to a message.
Class is a collection of methods and acts as a template for the creation of objects.
Delegation describes the forwarding of a request an object receives to another object. Objects delegate if they don’t have a method to handle certain requests.
Polymorphism is the characteristic of an object to respond differently to the same message because of changes in external parameters. This can be static polymorphism during compile time or dynamic polymorphism during runtime (JVM).
Cohesion is the degree of focus of a method (or class). Low cohesion means an unfocused variety of actions and low specialization.
Coupling describes the level of interaction between objects. High coupling of objects means low independence.
High cohesion and loose coupling is an important principle in software engineering. It results in strong focus and high independence and is desired for objects (and development teams).