Software continues to be more and more integral in our daily lives. Everyday devices have software in them, such as cars, phones, refrigerators, watches, medical devices, or planes. And organizations we rely on, from a bank or insurance company, to an energy plant or a traffic control system, all depend on reliable software. The existence of this software gives us many opportunities – living in smart homes, driving smart cars, and our smartphones and smartwatches assisting us with everything we need, and as more and more of these elements get connected to each other, we can add additional benefits and efficiencies, making our lives that much easier.
But all of this comes with a risk. Software security holes can be exploited to gain unprivileged access to any system. This may mean simple hacks like turning off our lights when we don’t expect it, or more alarming attacks, such as spying on us with our cameras, or emptying our bank accounts without our knowledge or permission. And software bugs that result in undesired behavior of an application can also cause similar issues, even without participation of a cybercriminal. For these reasons, software security is becoming increasingly top-of-mind for citizens around the world.
In 1999, MITRE Corporation (an American not-for-profit organization that operates research and development centers sponsored by the federal government) started to document known software security vulnerabilities on the Common Vulnerabilities and Exposures (CVE) list. The initial list consisted of 321 CVE entries, but it grew quickly, and currently (as of September 2018), the CVE list contains over 100,000 entries and is maintained by 92 CVE Numbering Authorities (CNAs) – different organizations from all around the world ( vulnerability researchers, product vendors, and bug bounty programs) that are authorized to assign CVE IDs to detected issues. The list is very widely used and is recommended by the National Institute of Standards and Technology (NIST), the U.S. Defense Information Systems Agency (DISA), and many more.
The MITRE Corporation wanted to make it easier to understand the roots of the most common problems and take appropriate actions to avoid similar issues in the future, so they categorized the CVE entries into groups depending on the type of issue, which ended with the publication of the Preliminary List of Vulnerability Examples for Researchers (PLOVER) document. Combining this work with other researches resulted in defining the Common Weakness Enumeration (CWE) list, which is a formal list of software weakness types. Currently, the CWE List Version 3.1 contains around 800 types of weaknesses grouped into 300 categories and views. Since this number can be overwhelming, the “Top 25 Most Dangerous Software Errors” list is maintained by the CWE in conjunction with the SANS Institute to maintain the most widespread and critical errors that can lead to serious vulnerabilities in software. The top of the current “Top 25” list, for instance, includes SQL Injections, OS Command Injections, Buffer Overflows, and Cross-site Scripting.
For industries in which safety is much more important than in others (i.e. airborne, automotive, or healthcare systems vs. television or other entertainment systems), the International Electrotechnical Commission (IEC) developed the IEC 61508: Functional Safety of Electrical / Electronic / Programmable Electronic Safety-related Systems. IEC 61508 is a general-purpose standard used in a variety of industries, but here are also standards dedicated for the specific industries, e.g.:
These standards consider specifics of a given domain, but their general idea – at least from the software point of view – is quite similar. All of them require (among other verification techniques) static analysis to be performed on the developed code and they provide some high-level guidelines on what needs to be done, while leaving lots of room for interpretation. They usually do not name any specific coding conventions or coding standards to be used, but e.g. ISO 26262 mentions MISRA C as an example of a coding guideline for the C programming language.
Writing secure code means writing code that will not be vulnerable, i.e. code that does not contain weaknesses that could potentially be exploited. It means writing code that complies with some “safe” patterns and the code that avoids “unsafe” patterns. And these patterns will be different for different programming languages. Of course, there is no single golden set of rules that could be followed to guarantee safety of the software. Some of the widely used coding standards that consider safety are:
MISRA C and MISRA C++ standards are developed by the Motor Industry Software Reliability Association (MISRA). The AUTOSAR C++ Coding Guidelines are developed by the AUTOSAR (AUTomotive Open System ARchitecture) development partnership. The JSF A V C++ Coding Standard was developed by the Lockheed Martin Corporation. SEI CERT C and C++ Coding Standards contain general rules meant to ensure the safety, reliability, and security of software systems developed in the C and C++ programming languages.
The rules in these standards are usually grouped into multiple categories to allow easier navigation, as the number of rules in given standard may be quite large, e.g.:
Considering the number of different functional safety standards, coding standards, and number of guidelines recommended or required by each standard, it is important to make good choices when starting the initiative of making the code secure.
If the software needs to be certified according to a specific functional safety standard (e.g. ISO 26262 for automotive or DO-178C for airborne), the initial decision is already made. But regardless, a choice needs to be made to determine the coding standard, or standards, or a subset of a standard to be enforced on the developed software. It may, but does not have to be, one of the standards mentioned above.
Next, an appropriate static code analysis tool needs to be chosen, as it is not possible to verify compliance with all these rules manually. There are both open source and commercial static analysis tools available. It is important to pick up a good one. Some of the factors that should be considered are:
Additionally, the CWE Community drives the CWE Compatibility and Effectiveness Program, which is a formal review and evaluation process for a product or a service. The list of “Officially CWE- Compatible” products and services contains currently 55 entries. Using the tool from this list ensures it has achieved the final stage of MITRE’s formal CWE Compatibility Program.
When the coding standard and appropriate tool are chosen, for the software projects started from scratch further work should be easy – simply integrate the tool with the CI system and make sure that no defect is left unattended. But usually, coding standard needs to be enforced on the software already under development.
In such cases, blind execution of the analysis on the whole code base may produce hundreds of defects being reported, which are hard to handle all together. Fortunately, there are multiple techniques that can be used to ease the process. For example, you can focus on the newly-written or modified code first, to make sure that at least no new defects are introduced from the moment the coding standard has been established.
Another good practice is to prioritize the reported defects to make sure the most severe ones are handled in the first place. As an example, CERT C and C++ Rules have risk assessment associated with them, allowing for easy prioritization of found defects.
A sophisticated static analysis tool can also help you focus on the rules with the highest severity first, increasing the number of rules you’re attending to as the more severe defects are getting fixed.
The most important part is to make sure that analysis is followed by appropriate actions taken by the development team. It does not matter how good the reports from the static analysis are if they are not used by the developers to fix the code, leading to more safe and secure software products. Taking the time to choose the right static analysis solution and coding standards will start you on a path to success.
Michał is a Project Lead Engineer at Parasoft, specialized in applying Parasoft's products for use in safety-related applications. Michał drives development of the static analysis engine used by the Parasoft's development testing solution.