CERT har ett pågående projekt för att utveckla kodningsregler och rekommendationer för att skriva säkrare program i C och C++. Reglerna utvecklas som ett öppet projekt och utvecklingen sker på projektets webbplats.
Här hittar du reglerna för C-kod och här hittar du reglerna för C++-kod.
Reglerna tar upp ett stort antal aspekter, vilket en snabb lista med kategorierna för C-kod visar:
01. Preprocessor (PRE)
02. Declarations and Initialization (DCL)
03. Expressions (EXP)
04. Integers (INT)
05. Floating Point (FLP)
06. Arrays (ARR)
07. Characters and Strings (STR)
08. Memory Management (MEM)
09. Input Output (FIO)
10. Temporary Files (TMP)
11. Environment (ENV)
12. Signals (SIG)
13. Error Handling (ERR)
14. Miscellaneous (MSC)
50. POSIX (POS)
99. The Void
Under de olika kategorierna kommer sedan ett antal regler som alla följer en gemensam form med beskrivning exempel, analys av säkerhetsproblem och referenser. Ett exemåel är INT07-A. Only use signed or unsigned char type for numeric values:
The three types char, signed char, and unsigned char are collectively called the character types. Compilers have the latitude to define char to have the same range, representation, and behavior as either signed char or unsigned char. Irrespective of the choice made, char is a separate type from the other two and is not compatible with either.
Only use signed char and unsigned char types for the storage and use of numeric values, as this is the only way to (portably) guarantee the signedness of the character types.
Non-Compliant Code Example
In this non-compliant code example, the char-type variable c may be signed or unsigned. Assuming 8-bit, two’s complement character types, this code may either print out i/c = 5 (unsigned) or i/c = -17 (signed). As a result, it is much more difficult to reason about the correctness of a program without knowing if these integers are signed or unsigned.
char c = 200;
int i = 1000;
printf(“i/c = %dn”, i/c);
Compliant Solution
In this compliant solution, the variable c is declared as unsigned char. The subsequent division operation is now independent of the signedness of char and consequently has a predictable result.
unsigned char c = 200;
int i = 1000;
printf(“i/c = %dn”, i/c);
Risk Assessment
This is a subtle error that results in a disturbingly broad range of potentially severe vulnerabilities.
Recommendation Severity Likelihood Remediation Cost Priority Level
INT07-A 2 (medium) 2 (probable) 2 (medium) P8 L2
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[ISO/IEC 9899-1999] Section 6.2.5, “Types”
[MISRA 04] Rule 6.2, “Signed and unsigned char type shall be used only for the storage and use of numeric values”
Det finns även en bok från CERT på området av Robert C. Seacord:

För den som har bråttom har CERT även en lista på de tio viktigaste generella reglerna, regler som inte bara går att applicera på C och C++:
1. Validate input. Validate input from all untrusted data sources. Proper input validation can eliminate the vast majority of software vulnerabilities. Be suspicious of most external data sources, including command line arguments, network interfaces, environmental variables, and user controlled files [Seacord 05].
2. Heed compiler warnings. Compile code using the highest warning level available for your compiler and eliminate warnings by modifying the code [C MSC00-A, C++ MSC00-A].
3. Architect and design for security policies. Create a software architecture and design your software to implement and enforce security policies. For example, if your system requires different privileges at different times, consider dividing the system into distinct intercommunicating subsystems, each with an appropriate privilege set.
4. Keep it simple. Keep the design as simple and small as possible [Saltzer 74, Saltzer 75]. Complex designs increase the likelihood that errors will be made in their implementation, configuration, and use. Additionally, the effort required to achieve an appropriate level of assurance increases dramatically as security mechanisms become more complex.
5. Default deny. Base access decisions on permission rather than exclusion. This means that, by default, access is denied and the protection scheme identifies conditions under which access is permitted [Saltzer 74, Saltzer 75].
6. Adhere to the principle of least privilege. Every process should execute with the the least set of privileges necessary to complete the job. Any elevated permission should be held for a minimum time. This approach reduces the opportunities an attacker has to execute arbitrary code with elevated privileges [Saltzer 74, Saltzer 75].
7. Sanitize data sent to other systems. Sanitize all data passed to complex subsystems [C STR02-A] such as command shells, relational databases, and commercial off-the-shelf (COTS) components. Attackers may be able to invoke unused functionality in these components through the use of SQL, command, or other injection attacks. This is not necessarily an input validation problem because the complex subsystem being invoked does not understand the context in which the call is made. Because the calling process understands the context, it is responsible for sanitizing the data before invoking the subsystem.
8. Practice defense in depth. Manage risk with multiple defensive strategies, so that if one layer of defense turns out to be inadequate, another layer of defense can prevent a security flaw from becoming an exploitable vulnerability and/or limit the consequences of a successful exploit. For example, combining secure programming techniques with secure runtime environments should reduce the likelihood that vulnerabilities remaining in the code at deployment time can be exploited in the operational environment [Seacord 05].
9. Use effective quality assurance techniques. Good quality assurance techniques can be effective in identifying and eliminating vulnerabilities. Penetration testing, fuzz testing, and source code audits should all be incorporated as part of an effective quality assurance program. Independent security reviews can lead to more secure systems. External reviewers bring an independent perspective; for example, in identifying and correcting invalid assumptions [Seacord 05].
10. Adopt a secure coding standard. Develop and/or apply a secure coding standard for your target development language and platform.
Nu gäller det bara att till sig allt och börja applicera det också...