There’s No Good Reason to Ignore CERT C++
By Miroslaw Zielinski
December 20, 2018
4 min read
It is really difficult to find a justification for not following a security coding standard such as CERT C++. Here, learn what it’s all about.
Security is becoming a new mantra of software development teams, especially those who are responsible for the safety or mission-critical software. In the past, security was often a “feature” that teams tried to add to already-built systems, at the very end of the development cycle (frequently by spinning in vicious circles of pen-testing and fixing), but today we know that security is a solid engineering discipline supported with multiple research programs and standards.
If you want your system to be secure by design, you need to start at the very beginning of the development process and make sure that every line of created code follows security best practices. For teams who develop in C++, one of the best options to rely on is the SEI CERT C++ standard. Parasoft C/C++test is the only tool that supports this standard comprehensively, and is the most complete security testing and compliance solution on the market for C and C++ code.
CERT C++ coding guidelines in numbers
The SEI CERT C++ standard introduces a collection of rules to enforce secure coding practices and eliminate vulnerable code constructs. The standard is organized in 11 chapters that contain rules in specific topic areas. Unlike CERT C, the CERT C++ coding standard only has rules, and no recommendations (they are pending further review and development). SEI CERT C++ relies on the CERT C standard and embraces the subset of CERT C rules that apply to C++. At this time (bear in mind that CERT are living standards), there are 83 CERT C++ rules and 80 rules inherited from CERT C. The overview of the standard is presented in the chart below:
Starting with version 10.4.1, Parasoft C/C++test has full support for the CERT C++ coding guidelines. The test configuration (“SEI CERT C++ Rules”) enables all checkers from the original CERT C++ rule set and those from CERT C that are applicable for C++, which is precisely as CERT defines it to assure the security of your C++ codebase. Organizations developing with C and C++, including teams planning to switch to C++, can now rely on a single tool with consistent reporting.
Teams also benefit from dedicated compliance reporting for CERT C and C++, for building a sustainable compliance process. With reporting extensions, users can get a dynamic view into the compliance process and review the violations prioritized according to the CERT risk assessment framework.
CERT attributes every violation with scoring for the following three factors:
- Severity
- Likelihood
- Remediation cost
Priority is computed as a product of these three factors and divided into levels: L1, L2, and L3. L1 represents high severity violations, with high likelihood and low remediation cost. These are the ones that we are the most interested in fixing, as they indicate serious problems that are not complicated to remediate. Using CERT’s scoring framework provides great help in focusing efforts and enabling teams to make the best use of their time budgets.
In addition to widgets, violations explorers, and a risk scoring framework that helps you quickly orient yourself in the advancement of the compliance process, Parasoft’s reporting framework also saves you time by automatically generating compliance reports that are suitable for code audits. This is an exciting functionality if your organization is more formal with the development process. Learn more about the CERT compliance reporting framework in Arthur’s related blog.
How can you benefit from CERT C++?
C++ is a great language, and while it has many features of modern OO language, enabling it for designing a complex systems with advanced OO design patterns, it also offers great efficiency because it allows you to access memory directly through pointers without checking whether this access is correct.
Of course, these benefits come with a price. With C++, even very experienced software developers can create vulnerable code, most commonly due to memory access and management issues. Buffer overflows, use of dangling references, and integers overflows can all lead to undefined behavior, which can be exploited in multiple ways. An attacker can try arc injection (maliciously transferring control to the code existing in process memory, other than intended) or code injection (injecting code to the memory of running system) to gain control over a system with privileges of the compromised program, or even worse, with a kernel access level. Once that control is taken, losses can be devastating.
So, how can we prevent attackers penetrating our system? It isn’t possible to take an existing codebase and try to guess all possible security breaches. The best option currently available for C/C++ programmers is to create code in the first place that is free from certain constructs that are proven to be a source of security breaches.
So, let’s look at a simple illustration. The snippet of source code below is taken directly from the CERT C++ standard (rule EXP61-CPP).
auto g() { int i = 12; return [&] { i = 100; // Problem return i; }; } void f() { int j = g()(); }
In this example, the function g() returns a lambda, which implicitly captures the automatic local variable “i” by reference. This poorly-written code has at least one security vulnerability when lambda is returned from the g() call — the reference it captured will refer to a variable whose lifetime has ended (g function is gone). As a result, when the lambda is executed in f(), the use of the dangling reference in the lambda effects in undefined behavior. This undefined behavior may be exploited to get control over the program. The memory that was occupied by “i” within the lifetime of g function is already freed, and this chunk of stack is probably already reused for some other purposes, possibly a return address from the function call, which when overwritten can be used to execute arbitrary code.
This specific vulnerability is detectable by the rule, EXP61-CPP A lambda object must not outlive any of its reference captured objects. So source code that is compliant with CERT C++ should not contain any occurrences of this problem.
CERT C++ includes many more rules that can detect potential problems and will help you to promote secure coding practices. Security coding guidelines, when used consistently, can help harden your source code and is the most effective strategy to assure overall system security. And in these days, it is really difficult to find a justification for not following a security coding standard such as CERT C++.