The National Security Agency (NSA) has published guidance on how organizations can implement protections against common software memory safety issues.
Caused by how programs manage or allocate memory, logic errors, incorrect order of operations, or the use of uninitialized variables, software memory safety issues are often exploited for remote code execution (RCE).
Representing the most common cause of vulnerabilities in many cases (Microsoft and Google blame memory safety issues for 70% of their bugs), memory safety issues may also lead to incorrect program behavior and performance degradation.
According to the NSA, the first step towards eliminating memory safety issues is the use of a programming language that is not inherently opening the door to these vulnerabilities.
C and C++, which offer flexibility regarding the management of memory, rely heavily on the programmer for memory reference checks. As such, even the smallest errors may lead to exploitable vulnerabilities.
While software analysis tools may detect memory management defects and some protections may exist, using a memory safe software language can prevent or mitigate most of these issues, the NSA says.
The NSA recommends using a memory safe language when possible. While the use of added protections to non-memory safe languages and the use of memory safe languages do not provide absolute protection against exploitable memory issues, they do provide considerable protection.
The most common types of memory safety issues include buffer overflows (data is accessed outside the array’s bounds), memory leaks (memory is not freed after use), use-after-free, and race conditions, among others.
Malicious actors may use unusual inputs to cause unexpected memory behavior and exploit these vulnerabilities to execute code, access sensitive information, or perform other malicious activities. Fuzzing may help threat actors identify problematic inputs easier.
“Once an actor discovers they can crash the program with a particular input, they examine the code and work to determine what a specially crafted input could do. In the worst case, such an input could allow the actor to take control of the system on which the program is running,” the NSA says.
To prevent or mitigate the risks associated with memory safety, the NSA recommends that organizations use memory safe programming languages such as C#, Go, Java, Ruby, Rust, and Swift, but warns that this won’t eliminate issues completely, due to some non-memory safe actions or libraries.
The agency also recommends hardening non-memory safe languages through static and dynamic application security testing (SAST and DAST).
The compilation and execution environment, the NSA notes, can be used to make the exploitation of memory safety bugs more difficult, courtesy of options such as Control Flow Guard (CFG), Address Space Layout Randomization (ASLR), and Data Execution Prevention (DEP).
“Memory issues in software comprise a large portion of the exploitable vulnerabilities in existence. NSA advises organizations to consider making a strategic shift from programming languages that provide little or no inherent memory protection, to a memory safe language when possible. By using memory safe languages and available code hardening defenses, many memory vulnerabilities can be prevented, mitigated, or made very difficult for cyber actors to exploit,” the NSA concludes.
Related: Rust Gets a Dedicated Security Team