C/C++ includes our standard 18 Green Belt modules along with our standard 13 Green Belt Secure Development lesson. Each of our lessons are short and conclude with a brief ten question assessment. The learning module length is purposeful – they are perfect for filling gaps in a developer’s day while analyzing.
Secure Development Core Lesson Modules
Intro to Secure Development
The definition of secure development and it’s pieces. Each developer has secure development responsibilities. Secure development starts and ends with the developer. Your software, hardware, and infrastructure are only as safe as you make them. Developers are the first line of defense.
The need for secure coding, what are secure coding standards and how does a developer use them, and the potential dangers of Stack Overflow. Languages are complex. Secure coding is about creating code that is correct and secure.
Secure Coding Best Practices: Part 1
Explore the OWASP Proactive Controls, including Define Security Requirements, Leverage Security Frameworks and Libraries, Secure Database Access, Encode and Escape Data, and Validate All Inputs. OWASP Proactive Controls is security information written for developers, by developers.
Secure Coding Best Practices: Part 2
Explore the OWASP Proactive Controls, including Enforce Access Control, Protect Data Everywhere, Implement Security Logging and Monitoring, and Handle All Errors and Exceptions. OWASP Proactive Controls is security information written for developers, by developers.
In this module, we explain how a languages type system is categorized and what the main categories are. We discuss the difference between static and dynamic languages as well as weak and strongly typed languages.
Securing the Development Environment
The threats that your development environment faces, how to reduce development environment risk, and the ten tips to secure your development environment. Development environment threats are real and following simple tips to secure your development environment can significantly reduce your exposure.
Protecting your Code Repository
Why you need to protect your code repository, the security challenges in choosing a repository, the impact of not protecting access credentials and separating secrets in the source code. Your code is your product or application. If it is left unsecured, it could fall into the hands of a competitor.
Producing a Clean, Maintainable, & Secure Code Culture
The sources of complexity in software that led to security vulnerabilities and the twelve laws that act as the foundation for a clean, maintainable, and secure code culture. Developers must strive for secure code. Secure code is both clean and maintainable.
Potential security threats are impacting your release and deployment process and ways to improve the security of your release and deployment process. The release and deployment process is how our code gets delivered to our customers. The introduction of an unauthorized piece of code by an attacker could be devastating.
Designing a Secure App or Product
The four pillars of a secure application or product, secure application or product decisions, and the categories of the design of a secure application or product. A new application or product deserves a secure design. Security becomes a reality through careful design choices.
Thinking Like A Penetration Tester
The tools and methodologies to help a developer think like a penetration tester, how penetration testers use browsers and intercepting proxies, testing, fuzzing, and reverse engineering, and applying the knowledge of these topics to your world as a developer. Developers generally focus on the build; to better secure your applications, products, and systems, think like one who breaks.
Secure Design Principles in Action: Part 1
The economy of mechanism, secure the weakest link, establish trust boundaries, defense in-depth, don’t reinvent the wheel, usable security and default deny. Secure design principles require action to achieve “secure by design.”
Secure Design Principles in Action: Part 2
In this module, we explore secure design principles such as minimizing the attack surface, fail securely, least privileged, separation of duties, do not trust services/ infrastructure, and secure defaults. Employing a common understanding of secure design principles encourages secure design, and secure design equals fewer vulnerabilities.
C/C++ for Developers
Green Belt Path
Introduction and Specifications
A high-level perspective on vulnerabilities and exploits, the tools of the build and test pipeline, and essential standards. View your code from an attacker's point of view to start practicing secure coding.
Classes of Vulnerabilities, Part 1
Common vulnerability classes are impacting the C and C++ developer, including numbers and strings. C and C++ have types of vulnerabilities. To see the problems, you must know how to identify them. The attackers know.
Classes of Vulnerabilities, Part 2
Common vulnerability classes are impacting the C and C++ developers, including concurrency and logic. C and C++ have types of vulnerabilities. To see the problems, you must know how to identify them. The attackers know.
Classes of Vulnerabilities, Part 3
Common vulnerability classes are impacting the C and C++ developers, including memory. C and C++ have types of vulnerabilities. To see the problems, you must know how to identify them. The attackers know.
Anatomy of a Stack Buffer Overflow Exploit
The basic anatomy of shellcode, how shellcode is used in a stack buffer overflow, and mitigations that protect against stack execution. Understanding stack buffer overflow anatomy identifies consequences and gives a more unobstructed view of why mitigations are needed.
Various tools to detect security issues during development and testing, like static analysis and warnings. Dynamic analysis techniques using sanitizers and fuzzers. Compiler and OS mitigations like Stack Canaries, Address Space Layout Randomization and non-executable memory. Many bugs and vulnerabilities are hard to see in code review; they are often subtle edge case scenarios. Tooling and platform mitigations have significantly improved and instill confidence that your code is in fact correct.
Undefined Behavior & Compiler Optimizations
Explain Undefined Behavior and how it can impact program behavior in unexpected ways. Examples of Undefined Behavior. How compiler optimizations change program behavior in unexpected ways. Undefined Behavior (UB) is a fundamental concept in C and C++ that profoundly impacts program behavior and security. How one explains UB and compiler optimizations is essential when trying to code more securely.
Exploitable Programming Constructs with Memory: Part 1
How to detect and mitigate Stack Buffer Overflow (CWE-121), Heap Buffer Overflow (CWE-122), Buffer Underflow (CWE-124), and Incorrect Type Conversion (CWE-704). Memory bugs are common in C and C++ and are the root cause of most vulnerabilities. Knowing how to use the tools available will help you detect and fix these issues in your code.
Exploitable Programming Constructs with Memory: Part 2
How to detect and mitigate Use After Free (CWE-416), Double Free (CWE-415), and Uncontrolled Format String (CWE-134). Memory bugs are common in C and C++ and are the root cause of most vulnerabilities. Knowing how to use the tools available will help you detect and fix these issues in your code.
Exploitable Programming Constructs with Numbers
How to detect and mitigate Unsigned Integer Wraparound (CWE-190), Signed Integer Overflow (CWE-190), and Numeric Truncation (CWE-197). Many famous exploitable numerical programming constructs are detectable either at compile-time, in instrumented builds, or at runtime. Knowing how to use the tools available helps detect and fix these issues in your own code.
Secure Programming Practices: Part 1
Become familiar with several concepts from the C++ Core Guidelines, including CPL.1: Prefer C++ to C, SL.str.1: Use std::string to own character sequences, SL.str.5: Use std::byte to refer to byte values that do not necessarily represent characters, ES.27: Use std::array or stack_array for arrays on the stack, and SL.con.3: Avoid bounds errors. Many of the most vulnerable programming constructs in C++ are in pure C. A large part of newer C++ language features are to mitigate these types of bugs.
Secure Programming Practices: Part 2
Become familiar with several concepts from the C++ Core Guidelines, including R.1: Manage resources automatically using resource handles and RAII (Resource Acquisition Is Initialization), R.11: Avoid calling new and delete explicitly, ES.20: Always initialize an object, ES.48: Avoid casts, and ES.49: If you must use a cast, use a named cast. Memory handling and resource management, in general, are a rich source of bugs and causes many security issues. Using idioms like RAII to manage resource lifetimes can eliminate many of these issues.
Secure Programming Practices: Part 3
Become familiar with several concepts from the C++ Core Guidelines, including Enum.3: Prefer class enums over “plain” enums, NL.11: Make literals readable, ES.103: Don’t overflow, ES.104: Don’t underflow, ES.42: Keep use of pointers simple and straightforward, and I.7: State postconditions. Certain parts of C++ do not have easy workarounds and require careful handling. Some have partial or alternative solutions that should be considered.
Secure Programming Practices: Part 4
Become familiar with several concepts from the C++ Core Guidelines, including ES.1: Prefer the standard library to other libraries and to “handcrafted code”, SL.io.3: Prefer iostreams for I/O, F.53: Avoid capturing by reference in lambdas that will be used nonlocally, including returned, stored on the heap, or passed to another thread, F.54: If you capture ‘this’, capture all variables explicitly (no default capture), Con.2: By default, make member functions const, C.128: Virtual functions should specify exactly one of virtual, override, or final. Test and audit libraries to reduce the risk of security issues. When implementing your own code, it is possible to make it more secure by using the compiler to enforce your intentions.
Different ways of writing the most vulnerable code possible, including evaluation order, sequence point violation, compiler differences, and a lack of input validation/sanitization. Looking at how to do something badly can be a fun way to see what we should do.
Different ways of writing the most vulnerable code possible, including ignore how the optimizer can and will remove critical code, write code that allows buffer overflows, disable stack protection, disable ASLR whenever you can, and avoid hardware and operating systems that enforce DEP/W^X/NX-bit. Looking at how to do something badly can be a fun way to see what we should do.
Different ways of writing the most vulnerable code possible, including making it easy to find many ROP gadgets in your program, skip integrity checks when installing and running new software, write insecure code by leaking information, and never let other programmers review your code. Looking at how to do something badly can be a fun way to see what we should do.
Walk through a sample vulnerable program and understand its security weaknesses as you disable various protection mechanisms. Create an automated exploit from a known vulnerable program. By looking at this fun program (War Games) from an attacker’s perspective, it prepares the developer to embrace the attacker mindset.