先丢出美国国家安全局的一篇文章:NSA Releases Guidance on How to Protect Against Software Memory Safety Issues:

This article is translated from two articles. The first is an interpretation of the NSA's "Software Memory Security" network security information table. The second is about popularizing what memory security is and why is it important?
Part 1: To avoid memory attacks, the NSA advocates Rust, C#, Go, Java, Ruby, and Swift, but puts C and C++ aside
This article comes from translation (Google Translate Plus).
Original author: Liam Tung
Original title: NSA to developers: Think about switching from C and C++ to a memory safe programming language
Original link: https://www.example.com

For many developers, this may mean moving to C#, Go, Java, Ruby, Rust, and Swift.
The National Security Agency (NSA) is urging developers to turn to memory-safe languages-such as C#, Go, Java, Ruby, Rust and Swift--to protect their code from remote code execution or other hacking attacks.
Among the languages mentioned above, Java is the most widely used language for enterprise and Android application development, while Swift is the top 10 languages, thanks in part to iOS application development. In systems programming, there is growing attention to Rust as an alternative to C and C++.
"The NSA recommends that organizations consider a strategic shift from programming languages that provide little or no intrinsic memory protection (such as C/C ++) to memory-safe languages, where possible. Some examples of memory-safe languages include C#, Go, Java, Ruby, and Swift." The National Security Agency said.
该间谍机构援引谷歌和微软最近的研究表明,他们 70% 的安全问题(分别在 Chrome和 Windows 中)与内存相关,其中许多是使用 C 和 C++ 的结果,它们更容易出现基于内存的漏洞.
另外: 网络安全、云和编码:为什么这三项技能将在 2023 年引领需求
美国国家安全局在“软件内存安全”网络安全信息表中指出:“恶意网络行为者可以利用这些漏洞进行远程代码执行或其他不利影响,这通常会危及设备并成为大规模网络入侵的第一步。 ”
"Commonly used languages such as C and C++ provide great freedom and flexibility in memory management while relying heavily on programmers to perform the required checks on memory references."
Therefore, the agency recommends using memory-safe languages whenever possible, whether for application development or system programming.
"The NSA recommends using memory-safe language whenever possible," it noted.
虽然大多数信息安全专家都熟悉这场关于内存安全语言的争论,但也许并非所有开发人员都熟悉。不过,考虑到这是一个存在了几十年的问题,也许他们应该这样做,正如 Java 的创建者 James Gosling 最近在一次关于如何以及为什么创建 Java 的讨论中指出的那样。
If anything, the NSA document provides developers with a clear, easy-to-understand language explanation of the technical reasons behind the switch to memory-safe language. Perhaps the most discussed language in terms of memory security is Rust, a leading candidate for "replacements" to C and C++.
继 Android 开源项目之后,Linux 内核 最近将 Rust 作为 C 的第二语言引入。这些项目不会替换旧的 C/C++ 代码,但会更喜欢 Rust 作为新代码。此外,Microsoft Azure CTO Mark Russinovich 最近呼吁所有开发人员在所有新项目中使用 Rust 而不是 C 和 C++。
"By taking advantage of these types of memory issues, malicious actors who are not bound by the normal expectations of software use may find that they can enter unusual inputs into programs, resulting in memory being accessed, written, allocated, or released in unexpected ways," the NSA explained.
但是——正如专家在关于 Rust 和 C/C++ 的辩论中指出的那样 ——美国国家安全局警告说,简单地使用内存安全语言并不能默认排除将内存错误引入软件。此外,语言通常允许不是用内存安全语言编写的库。
"Even with memory-safe languages, memory management is not entirely memory-safe. Most memory-safe languages recognize that software sometimes needs to perform unsafe memory management functions to complete certain tasks. As a result, you can use memory management tasks that are considered non-memory safe and allow programmers to perform potentially unsafe,"the NSA said.
"Some languages require anything that is memory insecure to be explicitly commented to make programmers and any reviewers of the program aware that it is unsafe. Memory-safe languages can also use libraries written in non-memory-safe languages and therefore can contain unsafe memory features. Although these methods that incorporate memory insecurity mechanisms subvert inherent memory security, they help locate locations where memory problems may exist, allowing additional review of these parts of code.
NSA 指出,某些内存安全语言可能会以性能成本为代价,这需要开发人员学习一门新语言。它还指出开发人员可以采取一些措施来强化非内存安全语言。例如, Google 的 Chrome 团队正在探索多种强化 C++ 的方法,但这些方法也会带来性能开销。在可预见的未来,C++ 将保留在 Chrome 的代码库中。
The NSA recommends static and dynamic application security testing to detect memory issues. It also recommends exploring memory-enforcing methods such as Control Flow Guard (CFG), which will restrict where code is executed. Similarly, address space layout randomization (ASLR) and data execution protection (DEP) are recommended.
Part 2 What is memory security and why is it important?
This article comes from translation (Google Translate Plus).
Source: https://www.example.com
Original title: What is memory safety and why does it matter?
Original link: https://www.example.com
Memory safety is a property of some programming languages that prevents programmers from introducing certain types of errors related to how memory is used. Because memory security vulnerabilities are usually security issues, memory-safe languages are more secure than non-memory-safe languages.
Memory-safe languages include Rust, Go, C#, Java, Swift, Python, and JavaScript. Memory-insecure languages include C, C++, and assembly language.
Types of memory security vulnerabilities
To start understanding memory security vulnerabilities, we will consider an example application that maintains a to-do list for many users. We will learn about several of the most common types of memory-safe errors that can occur in memory-insecure programs.
Reading and writing across borders
What happens if we have a to-do list of ten items and we ask for the eleventh item? Obviously we should have received some kind of error. If we ask for the first term of denial, we should also get an error.
In these cases, memory-insecure languages may allow programmers to read any memory content that exists just before or after the valid content of the list. This is called a cross-border reading. Memory before the first item in the list may be the last item in someone else's list. Memory after the last item in the list may be the first item in someone else's list. Access to this memory would be a serious security hole! Programmers can prevent out-of-bounds reads by carefully checking the length of the index and list of items they require, but programmers can make mistakes. It is best to use a memory-safe language that protects you and your users from such errors by default.
In memory-safe languages, we get errors at compile time or crash at run time. A program crash may seem serious, but it's better than letting users steal each other's data!
A closely related vulnerability is cross-border writing. In this case, suppose we try to change the eleventh item or negative first item on the to-do list. Now we are changing other people's to-do lists!
use after free
Imagine we delete a to-do list and then request the first item on that list. Obviously we should have received an error because we should not have been able to retrieve items from the deleted list. Memory-insecure languages allow programs to take the memory they have completed and can now use it for other purposes. Places in memory may now contain other people's to-do lists! This is called a post-release use vulnerability.
How common are memory security vulnerabilities?
极其。最近的一项研究发现,iOS 和 macOS 中 60-70% 的漏洞是内存安全漏洞。Microsoft 估计,在过去十年中,其产品中的所有漏洞中有 70% 是内存安全问题。谷歌估计 90% 的 Android 漏洞都是内存安全问题。对被发现广泛被利用的 0-day 的分析发现,超过 80% 的被利用漏洞是内存安全问题1。
2003 年的Slammer 蠕虫(这是一种专门衡量软件漏洞的方法,它不包括诸如凭据网络钓鱼之类的非常普遍的事情。)是缓冲区溢出(越界写入)。WannaCry(越界写入)也是如此。针对 iPhone的Trident 漏洞利用了三个不同的内存安全漏洞(两个释放后使用和一个越界读取)。HeartBleed是内存安全问题(越界读取)。Android 上的Stagefright也是如此(越界写入)。glibc 中的Ghost漏洞?你打赌(越界写)。
由于 C 和 C++ 不是内存安全的,因此这些漏洞以及利用其他漏洞成为可能。编写大量 C 和 C++ 的组织不可避免地会产生大量漏洞,这些漏洞可直接归因于缺乏内存安全性。这些弱点被利用,给医院、持不同政见者和卫生政策专家带来危险。使用 C 和 C++对社会不利,对您的声誉不利,对您的客户不利。
What other issues are related to memory-insecure languages?
Memory-insecure languages can also have a negative impact on stability, developer productivity, and application performance.
Because memory-insecure languages tend to experience more errors and crashes, they can greatly affect application stability. Even if crashes are not security-sensitive, they are still a very bad experience for users.
To make matters worse, it is difficult for developers to track down these errors. Memory corruption often causes the crash to occur far away from the actual location of the error. When multiple threads are involved, small differences in thread runtime can trigger other errors, making it more difficult to reproduce the error. The result is that developers often have to stare at crash reports for hours to determine the cause of memory corruption errors. These bugs may not be fixed for months, and developers are fully convinced that the bug exists but don't know how to make progress in discovering its cause and fixing it.
Finally, there is performance. Over the past few decades, one can count on CPUs to get faster every year or two. This is no longer the case. Instead, the CPU now comes with more cores. To take advantage of the extra kernel, developers need to write multithreaded code.
Unfortunately, multithreading exacerbates problems associated with lack of memory security, so efforts to leverage multicore CPUs in C and C++ are often tricky. For example-Mozilla tried multiple times to introduce multithreading into Firefox's C++ CSS subsystem before finally (successfully) rewriting the system with multithreading Rust, but all failed.
What is the right way forward?
Use memory-safe language! There are many great options. Write an operating system kernel or a web browser? Consider Rust! Build for iOS and macOS? Swift can do it. Web server? Go is a good choice. These are just a few examples, and there are many other excellent memory-safe languages to choose from (and many other wonderful use-case pairings!).
Changing the programming language your organization uses is not easy. That means changing the skills you look for when hiring, it means retraining your employees, and it means rewriting a lot of code. Still, we believe this will be necessary in the long run, so we want to explain why alternatives to new programming languages have not been successful.
If we take for granted that using unsafe languages creates vulnerabilities, the question we want to ask is: Can we adopt techniques to reduce this risk without forcing ourselves to completely change the programming language? The answer is yes. Not all projects written in unsafe languages are equally unsafe and unreliable.
Some practices that can reduce the risk of using unsafe language are:
- 使用一些现代 C++ 惯用语可以帮助生成更安全可靠的代码
- 使用fuzzers和sanitizers帮助在将错误投入生产之前找到它们
- Use exploit mitigations to help make it more difficult to exploit vulnerabilities
- Separation of authority, even if the vulnerability is exploited, the explosion radius is smaller
These practices meaningfully reduce the risk of using unsafe languages, and if we fail to persuade you to change the language and you plan to continue writing C and C++, they are necessary. Unfortunately, they are also grossly inadequate.
浏览器和操作系统开发人员是开发现代 C++ 惯用语、fuzzers、sanitizers、漏洞利用缓解和权限分离技术的最前沿人员——正是我们在开始时通过有关内存安全问题普遍性的统计数据强调的群体。尽管这些团队在这些技术上进行了投资,但他们使用不安全的语言却拖累了他们。在大型黑客大赛pwn2own上,2019年这些产品被利用的漏洞中有一半以上是由于缺乏内存安全,除了一个例外,每一次成功的攻击都至少利用了一个内存安全漏洞。
Is it really feasible to give up C and C++?
Hopefully by now, we have convinced you that unsafe languages like C and C++ are the root cause of a lot of insecurity in our products, and that while there are steps you can take to reduce the risk, you can't come close to eliminating it. All of this may still make you feel like changing the programming language you use to generate millions of lines of code is an overwhelming task. By breaking it down into manageable parts, we can begin to make progress-our goal is not to rewrite the world with a big bang, but to make progress in reducing risk.
The first is a brand new project. For these, you can choose to simply use a memory-safe language. These projects have the lowest risk because you don't need to start by rewriting any code, although projects like this often do require improved testing or deployment infrastructure to support new programming languages. This is the approach taken by ChromeOS's CrosVM, a new component of the operating system.
如果您没有新项目,下一个寻找机会使用内存安全语言的地方是现有项目的新组件。一些内存安全语言对与 C 和 C++ 代码库(例如 Rust 和 Swift)的互操作提供了一流的支持。这需要稍高的初始投资,因为它需要集成到构建系统中,以及使用新语言为需要跨越两种语言之间的边界传递的对象和数据构建抽象。当WebAuthn作为 Firefox 的一个新组件实现时,以及一个支持在 Rust 中编写 Linux 内核模块的项目,就成功地使用了这种策略。
What the first two methods have in common is that they both deal with new code. This has the advantage of clearly defined points of interaction with existing code and getting started without having to rewrite anything. It also provides you with the opportunity to stop the bleeding: there are no new components that use unsafe languages, and we will gradually process existing code. Adoption is more challenging for projects that don't have any natural new components to start using a memory-safe language.
In this case, you need to find some existing components to rewrite unsafe language to safe language. It's best if the components you choose are those you have already considered rewriting: maybe for performance, security, or because the code is too difficult to maintain. You should try to choose the smallest possible range for your first memory-safe rewrite to help the project succeed and release it as quickly as possible; this helps minimize the risks inherent in rewriting. Stylo, who rewritten Firefox's CSS engine with Rust, is a successful example of this approach.
No matter which approach is best for your organization, there are a few things you need to keep in mind to maximize your chances of success. The first is to make sure you have internal supporters and senior engineers who can provide code review and guidance in a language that is new to many team members. A natural extension of this is to ensure that engineers who will work in the new language have available resources, such as books, training or internal guides. Finally, you need to ensure that the new language has the same shared infrastructure as the old language, such as building systems, testing, deployment, crash reporting, and other integrations.
conclusion
Adopting a new programming language and starting the process of migrating to it. It requires planning, resource allocation and ultimate investment across the organization. Life would be much easier if we didn't have to think about these things. Unfortunately, a review of the data clearly shows that we simply cannot consider continuing to use unsafe language for security-sensitive projects.
Data proves time and time again that when projects use unsafe languages such as C and C++, they are plagued by a large number of security vulnerabilities. No matter how talented the engineer is or how much the investment is in privilege reduction and utilization mitigation, using a memory-insecure language will only cause too many errors. These errors greatly reduce safety, stability and productivity.
Fortunately, we don't need to be satisfied with the status quo. In the past few years, great alternatives to C and C++ have emerged, such as Rust, Swift, and Go. This means we don't have to keep memory corruption vulnerabilities around our necks as an albatross for many years to come, as long as we choose not to. We look forward to the day when choosing to use unsafe language is considered negligent because there is no multi-factor authentication or no encryption of data in transit.
Thanks to Alex Gainer
经许可,此解释基于 Alex Gaynor 的博客文章工程副总裁的内存不安全简介。
this paper summarizes
I hope you can get something from these two translations.