站点图标 江湖人士

美國國家安全局推薦C#,Go,Java等語言做爲程序開發語言

前幾天中,美國國家安全局推薦C#,Go,Java等語言做爲程序開發語言,即2022年11月10日的時候,NSA 發佈有關如何防範軟體記憶體安全問題的指南,做爲一個C#開發者對此第一時間找到了官方原文,確認了美國國家安全局的官網確實髮有此文。

原文地址:NSA 發佈有關如何防範軟體記憶體安全問題的指南

以下部分是翻譯文本:

馬里蘭州米德堡 – 美國國家安全局(NSA)今天發佈了指南,以幫助軟體開發人員和操作員預防和緩解軟體記憶體安全問題,這些問題佔可利用漏洞的很大一部分。

“軟體記憶體安全”網路安全資訊表強調了惡意網路參與者如何利用糟糕的記憶體管理問題來訪問敏感資訊、頒布未經授權的代碼執行以及造成其他負面影響。

“記憶體管理問題已經被利用了幾十年,今天仍然非常普遍,”網络安全技術總監Neal Ziring說。“在開發軟體時,我們必須始終如一地使用記憶體安全語言和其他保護措施,以消除惡意網路行為者的這些弱點。

微軟和谷歌都表示,軟體記憶體安全問題是他們大約70%的漏洞的背後問題。記憶體管理不善也可能導致技術問題,例如不正確的程序結果、程式性能隨時間推移而下降以及程序崩潰。

NSA 建議組織盡可能使用記憶體安全語言,並通過代碼強化防禦(如編譯器選項、工具選項和操作系統配置)來增強保護。

NSA 發佈有關如何防範軟體記憶體安全問題的指南 > 國家安全局/中央安全域>文章

美國國家安全局推薦C#,Go,Java

美國國家安全局推薦C#,Go,Java等語言做爲程序開發語言

完整的報告可以在這裏看到:CSI_SOFTWARE_MEMORY_SAFETY.PDF (defense.gov),下面的內容是原文的翻譯件。

軟體記憶體安全(Software Memory Safety)

摘要(Executive summary)

Modern society relies heavily on software-based automation, implicitly trusting developers to write software that operates in the expected way and cannot be compromised for malicious purposes. While developers often perform rigorous testing to prepare the logic in software for surprising conditions, exploitable software vulnerabilities are still frequently based on memory issues. Examples include
overflowing a memory buffer and leveraging issues with how software allocates and deallocates memory. Microsoft® revealed at a conference in 2019 that from 2006 to 2018 70 percent of their vulnerabilities were due to memory safety issues. [1] Google® also found a similar percentage of memory safety vulnerabilities over several years in Chrome®. [2] Malicious cyber actors can exploit these vulnerabilities for remote code execution or other adverse effects, which can often compromise a device and be the first step in large-scale network intrusions.

現代社會嚴重依賴基於軟體的自動化,隱含地信任開發人員編寫以預期方式運行且不會因惡意目的而受到損害的軟體。雖然開發人員經常執行嚴格的測試,以準備軟體中的邏輯以應對意外情況,但可利用的軟體漏洞仍然經常基於記憶體問題。範例包括記憶體緩衝區溢出,並利用軟體如何分配和解分配記憶體的問題。微軟®在 2019 年的一次會議上透露,從 2006 年到 2018 年,他們 70% 的漏洞是由於記憶體安全問題造成的。[1] 谷歌®還在Chrome®中發現了類似比例的記憶體安全漏洞。[2] 惡意網路行為者可以利用這些漏洞進行遠端代碼執行或其他不利影響,這通常會危及設備,並成為大規模網路入侵的第一步。

Commonly used languages, such as C and C++, provide a lot of freedom and flexibility in memory management while relying heavily on the programmer to perform the needed checks on memory references. Simple mistakes can lead to exploitable memory-based vulnerabilities. Software analysis tools can detect many instances of memory management issues and operating environment options can also provide some protection, but inherent protections offered by memory safe software languages can prevent or mitigate most memory management issues. NSA recommends using a memory safe language when possible. While the use of added protections to nonmemory safe languages and the use of memory safe languages do not provide absolute protection against exploitable memory issues, they do provide considerable protection.Therefore, the overarching software community across the private sector, academia, and the U.S. Government have begun initiatives to drive the culture of software development towards utilizing memory safe languages. [3] [4] [5]

常用語言(如 C 和 C++)在記憶體管理方面提供了很大的自由度和靈活性,同時嚴重依賴程式師對記憶體引用執行所需的檢查。簡單的錯誤可能導致可利用的基於記憶體的漏洞。軟體分析工具可以檢測記憶體管理問題的許多實例,操作環境選項也可以提供一些保護,但記憶體安全軟體語言提供的固有保護可以防止或緩解大多數記憶體管理問題。NSA 建議盡可能使用記憶體安全語言。雖然對非記憶體安全語言使用附加保護和使用記憶體安全語言並不能提供針對可利用記憶體問題的絕對保護,但它們確實提供了相當大的保護。因此,私營部門、學術界和美國政府的總體軟體社區已經開始採取措施,推動軟體開發文化利用記憶體安全語言。[3] [4] [5]

記憶體安全問題(The memory safety problem)

How a software program manages memory is core to preventing many vulnerabilities and ensuring a program is robust. Exploiting poor or careless memory management can allow a malicious cyber actor to perform nefarious acts, such as crashing the program at will or changing the instructions of the executing program to do whatever the actor desires. Even un-exploitable issues with memory management can result in incorrect program results, degradation of the program’s performance over time, or seemingly random program crashes.

軟體程式如何管理記憶體是防止許多漏洞和確保程式健壯的核心。利用糟糕或粗心的記憶體管理可以讓惡意網路參與者執行惡意行為,例如隨意使程序崩潰或更改執行程式的指令以執行參與者想要的任何事情。即使是不可利用的記憶體管理問題也可能導致不正確的程序結果、程式性能隨時間推移而下降或看似隨機的程序崩潰。

Memory safety is a broad category of issues related to how a program manages memory. One common issue is called a “buffer overflow” where data is accessed outside the bounds of an array. Other common issues relate to memory allocation. Languages can allocate new memory locations as a program is executing and then deallocate the memory, also called releasing or freeing the memory, later when the memory is no longer needed. But if this is not done carefully by the developer, new memory may be allocated again and again as the program executes. Consequently, memory is not always freed when it is no longer needed, resulting in a memory leak that could cause the program to eventually run out of available memory. Due to logic errors, programs can also attempt to use memory that has been freed, or even free memory that has already been freed. Another issue can arise when languages allow the use of a variable that has not been initialized, resulting in the variable using the value that was previously set at that location in memory. Finally, another challenging issue is called a race condition. This issue can occur when a program’s results depend on the order of operation of two parts of the program accessing the same data. All of these memory issues are much too common occurrences.

記憶體安全是與程式如何管理記憶體相關的一類廣泛的問題。一個常見的問題稱為「緩衝區溢出」 ,其中數據是在數位邊界之外訪問的。其他常見問題與記憶體分配有關。語言可以在程序執行時分配新的記憶體位置,然後在不再需要記憶體時釋放記憶體,也稱為釋放或釋放記憶體。但是,如果開發人員沒有仔細完成此操作,則在程序執行時可能會一次又一次地分配新記憶體。因此,當不再需要記憶體時,記憶體並不總是被釋放,從而導致記憶體洩漏,最終可能導致程式耗盡可用記憶體。由於邏輯錯誤,程式還可以嘗試使用已釋放的記憶體,甚至已釋放的記憶體。當語言允許使用尚未初始化的變數時,可能會出現另一個問題,從而導致變數使用以前在記憶體中該位置設置的值。最後,另一個具有挑戰性的問題稱為競爭條件。當程式的結果取決於訪問相同數據的程式的兩個部分的操作順序時,可能會出現此問題。所有這些記憶體問題都非常常見。

By exploiting these types of memory issues, malicious actors—who are not bound by normal expectations of software use—may find that they can enter unusual inputs into the program, causing memory to be accessed, written, allocated, or deallocated in unexpected ways. In some cases, a malicious actor can exploit these memory management mistakes to access sensitive information, execute unauthorized code, or cause other negative impacts. Since it may take a lot of experimenting with unusual inputs to find one that causes an unexpected response, actors may use a technique called “fuzzing” to either randomly or intelligently craft multitudes of input values to the program until one is found that causes the program to crash. Advances in fuzzing tools and techniques have made finding problematic inputs easier for malicious actors in recent years. 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.

通過利用這些類型的記憶體問題,不受軟體使用正常期望約束的惡意行為者可能會發現他們可以在程式中輸入異常輸入,從而導致以意外方式訪問、寫入、分配或釋放記憶體。在某些情況下,惡意行為者可以利用這些記憶體管理錯誤來訪問敏感資訊、執行未經授權的代碼或造成其他負面影響。由於可能需要對異常輸入進行大量實驗才能找到導致意外響應的輸入,因此參與者可能會使用一種稱為「模糊測試」的技術來隨機或智慧地為程式製作大量輸入值,直到找到導致程式崩潰的輸入值。近年來,模糊測試工具和技術的進步使惡意行為者更容易找到有問題的輸入。一旦參與者發現他們可以使用特定輸入使程式崩潰,他們就會檢查代碼並確定特製輸入可以做什麼。在最壞的情況下,這樣的輸入可能允許參與者控制運行程序的系統。

記憶體安全語言(Memory safe languages)

Using a memory safe language can help prevent programmers from introducing certain types of memory-related issues. Memory is managed automatically as part of the computer language; it does not rely on the programmer adding code to implement memory protections. The language institutes automatic protections using a combination of compile time and runtime checks. These inherent language features protect the programmer from introducing memory management mistakes unintentionally. Examples of memory safe language include C#, Go, Java®, Ruby™, Rust®, and Swift®.

使用記憶體安全語言有助於防止程式師引入某些類型的記憶體相關問題。記憶體作為計算機語言的一部分自動管理;它不依賴於程式師添加代碼來實現記憶體保護。該語言使用編譯時和運行時檢查的組合來建立自動保護。這些固有的語言功能可防止程式師無意中引入記憶體管理錯誤。記憶體安全語言的示例包括C#,Go,Java,Ruby®™,Rust®和Swift®。

Even with a memory safe language, memory management is not entirely memory safe. Most memory safe languages recognize that software sometimes needs to perform an unsafe memory management function to accomplish certain tasks. As a result, classes or functions are available that are recognized as non-memory safe and allow the programmer to perform a potentially unsafe memory management task. Some languages require anything memory unsafe to be explicitly annotated as such to make the programmer 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 thus can contain unsafe memory functionality. Although these ways of including memory unsafe mechanisms subvert the inherent memory safety, they help to localize where memory problems could exist, allowing for extra scrutiny on those sections of code.

即使使用記憶體安全語言,記憶體管理也不是完全記憶體安全的。大多數記憶體安全語言認識到軟體有時需要執行不安全的記憶體管理功能來完成某些任務。因此,可以使用被識別為非記憶體安全的類或函數,並允許程式師執行潛在的不安全記憶體管理任務。某些語言要求顯式註釋任何不安全的記憶體,以使程式師和程式的任何審閱者意識到它是不安全的。記憶體安全語言還可以使用以非記憶體安全語言編寫的庫,因此可以包含不安全的記憶體功能。儘管這些包含記憶體不安全機制的方法破壞了固有的記憶體安全性,但它們有助於定位可能存在記憶體問題的位置,從而允許對這些代碼部分進行額外的審查。

Languages vary in their degree of memory safety instituted through inherent protections and mitigations. Some languages provide only relatively minimal memory safety whereas some languages are very strict and provide considerable protections by controlling how memory is allocated, accessed, and managed. For languages with an extreme level of inherent protection, considerable work may be needed to simply get the program to compile due to the checks and protections.

語言通過固有的保護和緩解措施建立的記憶體安全程度各不相同。某些語言僅提供相對最低的記憶體安全性,而某些語言非常嚴格,並通過控制記憶體的分配、訪問和管理方式提供相當大的保護。對於具有極端固有保護級別的語言,由於檢查和保護,可能需要大量工作才能簡單地編譯程式。

Memory safety can be costly in performance and flexibility. Most memory safe languages require some sort of garbage collection to reclaim memory that has been allocated, but is no longer needed by the program. There is also considerable performance overhead associated with checking the bounds on every array access that could potentially be outside of the array.

記憶體安全在性能和靈活性方面可能代價高昂。大多數記憶體安全語言都需要某種垃圾回收來回收已分配但程式不再需要的記憶體。檢查可能位於陣列外部的每個陣列訪問的邊界也會產生相當大的性能開銷。

Alternatively, a similar performance hit can exist in a non-memory safe language due to the checks a programmer adds to the program to perform bounds checking and other memory management protections. Additional costs of using non-memory safe languages include hard-to-diagnose memory corruption and occasional program crashes along with the potential for exploitation of memory access vulnerabilities.

或者,由於程式師向程式添加檢查以執行邊界檢查和其他記憶體管理保護,因此在非記憶體安全語言中可能存在類似的性能影響。使用非記憶體安全語言的額外成本包括難以診斷的記憶體損壞和偶爾的程序崩潰以及利用記憶體訪問漏洞的可能性。

It is not trivial to shift a mature software development infrastructure from one computer language to another. Skilled programmers need to be trained in a new language and there is an efficiency hit when using a new language. Programmers must endure a learning curve and work their way through any “newbie” mistakes. While another approach is to hire programmers skilled in a memory safe language, they too will have their own learning curve for understanding the existing code base and the domain in which the software will function.

將成熟的軟體開發基礎設施從一種計算機語言轉移到另一種計算機語言並非易事。熟練的程式師需要接受新語言的培訓,並且在使用新語言時效率會受到影響。程式師必須忍受學習曲線,並克服任何「新手」錯誤。雖然另一種方法是僱用精通記憶體安全語言的程式師,但他們也將有自己的學習曲線來理解現有的代碼庫和軟體將在其中運行的領域。

應用程式安全測試(Application security testing)

Several mechanisms can be used to harden non-memory safe languages to make them more memory safe. Analyzing the software using static and dynamic application security testing (SAST and DAST) can identify memory use issues in software.

可以使用多種機制來強化非記憶體安全語言,使其對記憶體更加安全。使用靜態和動態應用程式安全測試(SAST 和 DAST)分析軟體可以識別軟體中的記憶體使用問題。

Static analysis examines the source code to find potential security issues. Using SAST allows all of the code to be examined, but it can generate a considerable number of false positives through identifying potential issues incorrectly. However, SAST can be used throughout the development of the software allowing issues to be identified and fixed early in the software development process. Rigorous tests have shown that even the best-performing SAST tools only identify a portion of memory issues in even the simplest software programs and usually generate many false positives.

靜態分析檢查原始程式碼以查找潛在的安全問題。使用 SAST 可以檢查所有代碼,但它可能會通過錯誤地識別潛在問題來生成大量誤報。但是,SAST可以在整個軟體開發過程中使用,從而可以在軟體開發過程的早期識別和修復問題。嚴格的測試表明,即使是性能最好的SAST工具也只能識別最簡單的軟體程式中的一部分記憶體問題,並且通常會產生許多誤報。

In contrast to SAST, dynamic analysis examines the code while it is executing. DAST requires a running application. This means most issues will not be identified until late in the development cycle, making the identified problem more expensive to fix and regressively test. DAST can only identify issues with code that is on the execution path when the tool is run, so code coverage is also an issue. However, DAST has a much lower percentage of false positives than SAST. Issues such as a memory leak can be identified by DAST, but the underlying cause of the memory issue may be very difficult to identify in the software.

與 SAST 相比,動態分析在執行代碼時檢查代碼。DAST 需要一個正在運行的應用程式。這意味著大多數問題要到開發周期的後期才能識別出來,這使得識別出的問題修復和回歸測試的成本更高。DAST 只能在工具運行時識別執行路徑上的代碼問題,因此代碼覆蓋率也是一個問題。但是,DAST 的誤報百分比比 SAST 低得多。諸如記憶體洩漏之類的問題可以通過 DAST 識別,但記憶體問題的根本原因可能很難在軟體中識別。

Neither SAST nor DAST can make non-memory safe code totally memory safe. Since all tools have their strengths and weaknesses, it is recommended that multiple SAST and DAST tools be run to increase the chances that memory or other issues are identified. Working through the issues identified by the tools can take considerable work, but will result in more robust and secure code. Vulnerability correlation tools can intake the results from multiple tools and integrate them into a single report to simplify and help prioritize analysis.

SAST 和 DAST 都不能使非記憶體安全代碼完全記憶體安全。由於所有工具都有其優點和缺點,因此建議運行多個 SAST 和 DAST 工具,以增加識別記憶體或其他問題的機會。解決工具標識的問題可能需要大量工作,但會生成更可靠、更安全的代碼。漏洞關聯工具可以從多個工具中提取結果,並將其集成到單個報告中,以簡化分析並幫助確定分析的優先順序。

反漏洞利用功能(Anti-exploitation features)

The compilation and execution environment can be used to make it more difficult for cyber actors to exploit memory management issues. Most of these added features focus on limiting where code can be executed in memory and making memory layout unpredictable. As a result, this reduces a malicious actor’s opportunities to use the exploitation tradecraft of executing data as code and overwriting a return address to direct program flow to a nefarious location.

編譯和執行環境可用於使網路參與者更難利用記憶體管理問題。這些添加的功能大多側重於限制代碼在記憶體中執行的位置,並使記憶體佈局不可預測。因此,這減少了惡意行為者使用將數據作為代碼執行並覆蓋返回位址以將程式流定向到惡意位置的利用交易的機會。

Leveraging options, such as Control Flow Guard (CFG), will place restrictions on where code can be executed. Similarly, Address Space Layout Randomization (ASLR) and Data Execution Prevention (DEP) add unpredictability to where items are located in memory and prevent data from being executed as code. [6] [7] Bypassing ASLR and DEP is not insurmountable to a malicious actor, but it makes developing an exploit much more difficult and lowers the odds of an exploit succeeding. Anti-exploitation features can help mitigate vulnerabilities in both memory safe and non-memory safe languages.

利用控制流防護 (CFG) 等選項將對代碼的執行位置施加限制。同樣,位址空間佈局隨機化 (ASLR) 和數據執行保護 (DEP) 增加了項在記憶體中位置的不可預測性,並阻止數據作為代碼執行。[6] [7] 繞過 ASLR 和 DEP 對於惡意行為者來說並非不可克服,但它使開發漏洞變得更加困難,並降低了漏洞利用成功的幾率。反利用功能有助於緩解記憶體安全和非記憶體安全語言中的漏洞。

前方的路(The path forward)

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, such as C/C++, to a memory safe language when possible. Some examples of memory safe languages are C#, Go, Java, Ruby™, and Swift®. Memory safe languages provide differing degrees of memory usage protections, so available code hardening defenses, such as compiler options, tool analysis, and operating system configurations, should be used for their protections as well. 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.▪

軟體中的記憶體問題佔現有可利用漏洞的很大一部分。NSA建議組織考慮從
盡可能為記憶體安全語言提供很少或沒有固有記憶體保護的程式設計語言,例如 C/C++。記憶體安全語言的一些示例是C#,Go,Java,Ruby™和Swift®。記憶體安全語言提供不同程度的記憶體使用保護,因此也應使用可用的代碼強化防禦(如編譯器選項、工具分析和操作系統配置)來保護它們。通過使用記憶體安全語言和可用的代碼強化防禦,可以防止、緩解許多記憶體漏洞,或者使網路參與者很難利用這些漏洞。 ▪

美國國家安全局推薦C#,Go,Java等語言做爲程序開發語言
退出移动版