本文翻譯自兩篇文章,第一篇是對美國國家安全局在“軟件內存安全”網絡安全信息表的解讀,第二篇是普及什么是內存安全,為什么它很重要?
第一篇 為了避免內存攻擊,美國國家安全局提倡Rust、C#、Go、Java、Ruby 和 Swift,但將 C 和 C++ 置于一邊
本文來自翻譯(谷歌翻譯加持)。
原文作者:Liam Tung
原文標題:NSA to developers: Think about switching from C and C++ to a memory safe programming language
原文鏈接:https://www.zdnet.com/article/nsa-to-developers-think-about-switching-from-c-and-cpp-to-a-memory-safe-programming-language/
對于許多開發人員來說,這可能意味著轉向 C#、Go、Java、Ruby、Rust 和 Swift。
美國國家安全局 (NSA) 敦促開發人員轉向內存安全語言——例如 C#、Go、Java、Ruby、Rust 和 Swift——以保護他們的代碼免受遠程代碼執行或其他黑客攻擊。
在上面提到的語言中,Java 是企業和 Android 應用程序開發中使用最廣泛的語言,而 Swift 是前 10 名語言,部分歸功于 iOS 應用程序開發。在系統編程中,人們越來越關注 Rust 作為 C 和 C++ 的替代品。
“美國國家安全局建議組織考慮在可能的情況下從提供很少或不提供內在內存保護的編程語言(例如 C/C++)到內存安全語言的戰略轉變。內存安全語言的一些示例包括 C#、Go、Java、Ruby和Swift。”美國國家安全局說。
該間諜機構援引谷歌和微軟最近的研究表明,他們 70% 的安全問題[1](分別在 Chrome[2]和 Windows 中)與內存相關,其中許多是使用 C 和 C++ 的結果,它們更容易出現基于內存的漏洞.
另外:網絡安全、云和編碼:為什么這三項技能將在 2023 年引領需求[3]
美國國家安全局在“軟件內存安全”網絡安全信息表[4]中指出:“惡意網絡行為者可以利用這些漏洞進行遠程代碼執行或其他不利影響,這通常會危及設備并成為大規模網絡入侵的第一步。”
“C 和 C++ 等常用語言在內存管理方面提供了很大的自由度和靈活性,同時嚴重依賴程序員對內存引用執行所需的檢查。”
因此,該機構建議盡可能使用內存安全語言,無論是用于應用程序開發還是系統編程。
“NSA 建議盡可能使用內存安全語言,”它指出。
雖然大多數信息安全專家都熟悉這場關于內存安全語言的爭論,但也許并非所有開發人員都熟悉。不過,考慮到這是一個存在了幾十年的問題,也許他們應該這樣做,正如 Java 的創建者 James Gosling 最近在一次關于如何以及為什么創建 Java[5] 的討論中指出的那樣。
如果有的話,NSA 文件為開發人員提供了一個清晰、通俗易懂的語言解釋,說明了轉向內存安全語言背后的技術原因。在內存安全方面討論最多的語言可能是 Rust,它是 C 和 C++ 的“替代品”的主要候選語言。
繼 Android 開源項目之后,Linux 內核 最近將 Rust 作為 C 的第二語言引入[6]。這些項目不會替換舊的 C/C++ 代碼,但會更喜歡 Rust 作為新代碼。此外,Microsoft Azure CTO Mark Russinovich 最近呼吁所有開發人員在所有新項目中使用 Rust 而不是 C 和 C++[7]。
“通過利用這些類型的內存問題,不受軟件使用正常預期約束的惡意行為者可能會發現他們可以向程序輸入不尋常的輸入,導致以意想不到的方式訪問、寫入、分配或釋放內存,”美國國家安全局解釋道。
但是——正如專家在關于 Rust 和 C/C++ 的辯論[8]中指出的那樣 ——美國國家安全局警告說,簡單地使用內存安全語言并不能默認排除將內存錯誤引入軟件。此外,語言通常允許不是用內存安全語言編寫的庫。
“即使使用內存安全語言,內存管理也不完全是內存安全的。大多數內存安全語言都認識到軟件有時需要執行不安全的內存管理功能才能完成某些任務。因此,可以使用被認為是非內存安全并允許程序員執行可能不安全的內存管理任務,”美國國家安全局說。
“一些語言要求任何內存不安全的東西都被顯式注釋,以使程序員和程序的任何審閱者意識到它是不安全的。內存安全語言也可以使用以非內存安全語言編寫的庫,因此可以包含不安全的內存功能. 盡管這些包含內存不安全機制的方法顛覆了固有的內存安全性,但它們有助于定位可能存在內存問題的位置,從而允許對這些代碼部分進行額外的審查。
另外:網絡安全:這些是 2023 年需要擔心的新事物[9]
NSA 指出,某些內存安全語言可能會以性能成本為代價,這需要開發人員學習一門新語言。它還指出開發人員可以采取一些措施來強化非內存安全語言。例如, Google 的 Chrome 團隊正在探索多種強化 C++ 的[10]方法,但這些方法也會帶來性能開銷。在可預見的未來,C++ 將保留在 Chrome 的代碼庫中。
NSA 建議進行靜態和動態應用程序安全測試以發現內存問題。它還建議探索內存強化方法,例如 Control Flow Guard (CFG),這將限制代碼的執行位置。同樣,建議使用地址空間布局隨機化 (ASLR) 和數據執行保護 (DEP)。
第二篇 什么是內存安全,為什么它很重要?
本文來自翻譯(谷歌翻譯加持)。
出處:https://www.memorysafety.org
原文標題:What is memory safety and why does it matter?
原文鏈接:https://www.memorysafety.org/docs/memory-safety/
內存安全是一些編程語言的一個屬性,它可以防止程序員引入與內存使用方式相關的某些類型的錯誤。由于內存安全漏洞通常是安全問題,因此內存安全語言比非內存安全語言更安全。
內存安全語言包括 Rust、Go、C#、Java、Swift、Python 和 JavaScript。內存不安全的語言包括 C、C++ 和匯編語言。
內存安全漏洞的類型
為了開始理解內存安全漏洞,我們將考慮一個為許多用戶維護待辦事項列表的應用程序示例。我們將了解幾種最常見的內存安全錯誤類型,它們可能發生在內存不安全的程序中。
越界讀寫
如果我們有一個包含十項的待辦事項列表,而我們要求第十一項,會發生什么?顯然我們應該收到某種錯誤。如果我們要求否定的第一項,我們也應該得到一個錯誤。
在這些情況下,內存不安全的語言可能允許程序員讀取列表的有效內容之前或之后恰好存在的任何內存內容。這稱為越界讀取。列表第一項之前的內存可能是其他人列表的最后一項。列表最后一項之后的內存可能是其他人列表的第一項。訪問此內存將是一個嚴重的安全漏洞!程序員可以通過仔細檢查他們要求的項目的索引與列表的長度來防止越界讀取,但是程序員會犯錯誤。最好使用一種內存安全語言,默認情況下可以保護您和您的用戶免受此類錯誤的侵害。
在內存安全語言中,我們會在編譯時出錯或在運行時崩潰。程序崩潰看似嚴重,但總比讓用戶竊取彼此的數據要好!
一個密切相關的漏洞是越界寫入。在這種情況下,假設我們試圖更改待辦事項列表中的第十一項或否定的第一項。現在我們正在改變別人的待辦事項清單!
釋放后使用
想象一下,我們刪除了一個待辦事項列表,然后請求該列表的第一項。顯然我們應該收到一個錯誤,因為我們不應該能夠從已刪除的列表中獲取項目。內存不安全的語言允許程序獲取他們已經完成的內存,現在可以將其用于其他用途。內存中的位置現在可能包含其他人的待辦事項列表!這稱為釋放后使用漏洞。
內存安全漏洞有多普遍?
極其。最近的一項研究[11]發現,iOS 和 macOS 中 60-70% 的漏洞是內存安全漏洞。Microsoft 估計[12],在過去十年中,其產品中的所有漏洞中有 70% 是內存安全問題。谷歌估計[13] 90% 的 Android 漏洞都是內存安全問題。對被發現廣泛被利用的 0-day 的分析[14]發現,超過 80% 的被利用漏洞是內存安全問題1。
2003 年的Slammer 蠕蟲[15](這是一種專門衡量軟件漏洞的方法,它不包括諸如憑據網絡釣魚之類的非常普遍的事情。)是緩沖區溢出(越界寫入)。WannaCry[16](越界寫入)也是如此。針對 iPhone的Trident 漏洞[17]利用了三個不同的內存安全漏洞(兩個釋放后使用和一個越界讀取)。HeartBleed[18]是內存安全問題(越界讀取)。Android 上的Stagefright[19]也是如此(越界寫入)。glibc 中的Ghost漏洞[20]?你打賭(越界寫)。
由于 C 和 C++ 不是內存安全的,因此這些漏洞以及利用其他漏洞成為可能。編寫大量 C 和 C++ 的組織不可避免地會產生大量漏洞,這些漏洞可直接歸因于缺乏內存安全性。這些弱點被利用,給醫院[21]、持不同政見者[22]和衛生政策專家[23]帶來危險。使用 C 和 C++對社會[24]不利,對您的聲譽[25]不利,對您的客戶[26]不利。
與內存不安全的語言相關的還有哪些其他問題?
內存不安全的語言也會對穩定性、開發人員生產力和應用程序性能產生負面影響。
由于內存不安全的語言往往會出現更多錯誤和崩潰,因此會極大地影響應用程序的穩定性。即使崩潰不是安全敏感的,它們對用戶來說仍然是非常糟糕的體驗。
更糟糕的是,開發人員很難追蹤到這些錯誤。內存損壞通常會導致崩潰發生在距離錯誤實際位置很遠的地方。當涉及多線程時,線程運行時間的微小差異可能會觸發其他錯誤,從而導致更難重現錯誤。結果是開發人員通常需要盯著崩潰報告看幾個小時才能確定內存損壞錯誤的原因。這些錯誤可能幾個月都沒有修復,開發人員完全相信存在錯誤,但不知道如何在發現其原因和修復方面取得進展。
最后,還有性能。在過去的幾十年里,人們可以指望 CPU 每一兩年都變得更快。這已不再是這種情況。相反,CPU 現在帶有更多內核。為了利用額外的內核,開發人員需要編寫多線程代碼。
不幸的是,多線程加劇了與缺乏內存安全相關的問題,因此,在 C 和 C++ 中利用多核 CPU 的努力通常是棘手的。例如——在最終(成功)用多線程 Rust 重寫系統之前,Mozilla 多次嘗試將多線程引入 Firefox 的 C++ CSS 子系統,但均以失敗告終。
正確的前進道路是什么?
使用內存安全語言!有很多很棒的可供選擇。編寫操作系統內核或 Web 瀏覽器?考慮Rust!為 iOS 和 macOS 構建?Swift可以勝任。網絡服務器?Go 是個不錯的選擇。這些只是幾個例子,還有許多其他優秀的內存安全語言可供選擇(以及許多其他精彩的用例配對!)。
更改您的組織使用的編程語言并非輕而易舉。這意味著改變你在招聘時尋找的技能,這意味著對你的員工進行再培訓,這意味著重寫大量代碼。盡管如此,我們相信從長遠來看這是必需的,因此我們想說明為什么采用新編程語言的替代方案沒有成功。
如果我們理所當然地認為使用不安全的語言會產生一些漏洞,那么我們想問的問題是:我們是否可以采取一些技術來降低這種風險,而不用強迫自己完全改變編程語言?答案是肯定的。并非所有用不安全語言編寫的項目都同樣不安全和不可靠。
一些可以降低使用不安全語言風險的做法是:
使用一些現代 C++ 慣用語[27]可以幫助生成更安全可靠的代碼
使用fuzzers[28]和sanitizers[29]幫助在將錯誤投入生產之前找到它們
使用漏洞利用緩解措施來幫助增加利用漏洞的難度
權限分離,即使漏洞被利用,爆炸半徑也更小
這些做法有意義地降低了使用不安全語言的風險,如果我們未能說服您更換語言,而您打算繼續編寫 C 和 C++,那么采用這些做法勢在必行。不幸的是,它們也嚴重不足。
瀏覽器和操作系統開發人員是開發現代 C++ 慣用語、fuzzers[30]、sanitizers[31]、漏洞利用緩解和權限分離技術的最前沿人員——正是我們在開始時通過有關內存安全問題普遍性的統計數據強調的群體。盡管這些團隊在這些技術上進行了投資,但他們使用不安全的語言卻拖累了他們。在大型黑客大賽pwn2own上,2019年這些產品被利用的漏洞[32]中有一半以上是由于缺乏內存安全,除了一個例外,每一次成功的攻擊[33]都至少利用了一個內存安全漏洞。
放棄 C 和 C++ 真的可行嗎?
希望到現在為止,我們已經讓您相信,像 C 和 C++ 這樣的不安全語言是我們產品中大量不安全的根本原因,并且盡管您可以采取一些措施來降低風險,但您無法接近消除它。所有這些可能仍然讓你覺得改變你使用的編程語言,產生數百萬行代碼,是一個壓倒性的巨大任務。通過將其分解為可管理的部分,我們可以開始取得進展——我們的目標不是大爆炸式地重寫世界,而是在降低風險方面取得進展。
首先是全新的項目。對于這些,您可以選擇簡單地使用內存安全語言。這些項目的風險最低,因為您不需要從重寫任何代碼開始,盡管像這樣的項目通常確實需要改進測試或部署基礎設施以支持新的編程語言。這是 ChromeOS 的 CrosVM(操作系統的全新組件)所采用的方法。
如果您沒有新項目,下一個尋找機會使用內存安全語言的地方是現有項目的新組件。一些內存安全語言對與 C 和 C++ 代碼庫(例如 Rust 和 Swift)的互操作提供了一流的支持。這需要稍高的初始投資,因為它需要集成到構建系統中,以及使用新語言為需要跨越兩種語言之間的邊界傳遞的對象和數據構建抽象。當WebAuthn[34]作為 Firefox 的一個新組件實現時,以及一個支持在 Rust 中編寫 Linux 內核模塊[35]的項目,就成功地使用了這種策略。
前兩種方法的共同點是它們都處理新代碼。這具有與現有代碼定義明確的交互點的優勢,并且無需重寫任何內容即可開始工作。它還為您提供了止血的機會:沒有使用不安全語言的新組件,我們將逐步處理現有代碼。對于沒有任何自然的新組件來開始使用內存安全語言的項目,采用更具挑戰性。
在這種情況下,您需要尋找一些現有組件以將不安全語言重寫為安全語言。最好是您選擇的組件是您已經考慮重寫的組件:可能是為了性能、安全性,或者是因為代碼太難維護。你應該嘗試為你的第一次內存安全重寫選擇范圍盡可能小的東西,以幫助項目成功并盡快發布;這有助于將重寫中固有的風險降至最低。Stylo,用 Rust 重寫了 Firefox 的 CSS 引擎,是這種方法的一個成功例子。
無論哪種方法最適合您的組織,都需要牢記一些事項以最大程度地提高成功的機會。首先是確保你有內部支持者和高級工程師,他們可以使用對許多團隊成員來說都是新的語言提供代碼審查和指導。這樣做的自然延伸是確保將使用新語言工作的工程師有可用的資源,如書籍、培訓或內部指南。最后,您需要確保新語言擁有與舊語言相同的共享基礎設施,例如構建系統、測試、部署、崩潰報告和其他集成。
結論
采用一種新的編程語言并開始遷移到它的過程并不是一件容易的事。它需要整個組織的規劃、資源配置和最終投資。如果我們不必考慮這些事情,生活會容易得多。不幸的是,對數據的審查清楚地表明,我們根本不能考慮繼續為安全敏感項目使用不安全的語言。
數據一次又一次地證明,當項目使用 C 和 C++ 等不安全語言時,它們就會受到大量安全漏洞的困擾。無論工程師多么有才華,在權限減少和利用緩解方面的投資有多大,使用內存不安全的語言只會導致太多錯誤。這些錯誤大大降低了安全性、穩定性和生產力。
幸運的是,我們不需要滿足于現狀。在過去的幾年中,出現了 C 和 C++ 的絕佳替代品,例如 Rust、Swift 和 Go 等。這意味著我們不必在未來的許多年里將內存損壞漏洞作為一個信天翁掛在脖子上,只要我們選擇不這樣做。我們期待有一天,選擇使用不安全的語言被認為是疏忽大意,因為沒有多因素身份驗證或沒有加密傳輸中的數據。
感謝亞歷克斯蓋納
經許可,此解釋基于 Alex Gaynor 的博客文章工程副總裁的內存不安全簡介[36]。
本文總結
希望大家能從這兩篇譯文中得到些什么。
參考資料
[1]
他們 70% 的安全問題: https://www.zdnet.com/article/microsoft-70-percent-of-all-security-bugs-are-memory-safety-issues/
[2]Chrome: https://www.zdnet.com/article/chrome-70-of-all-security-bugs-are-memory-safety-issues/
[3]網絡安全、云和編碼:為什么這三項技能將在 2023 年引領需求: https://www.zdnet.com/article/cybersecurity-cloud-and-coding-why-these-three-skills-will-lead-demand-in-2023/
[4]美國國家安全局在“軟件內存安全”網絡安全信息表: https://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY.PDF
[5]如何以及為什么創建 Java: https://www.zdnet.com/article/programming-languages-java-founder-james-gosling-reveals-more-on-java-and-android/
[6]最近將 Rust 作為 C 的第二語言引入: https://www.zdnet.com/article/linus-torvalds-rust-will-go-into-linux-6-1/
[7]所有開發人員在所有新項目中使用 Rust 而不是 C 和 C++: https://www.zdnet.com/article/programming-languages-its-time-to-stop-using-c-and-c-for-new-projects-says-microsoft-azure-cto/
[8]關于 Rust 和 C/C++ 的辯論: https://www.zdnet.com/article/programming-languages-its-time-to-stop-using-c-and-c-for-new-projects-says-microsoft-azure-cto/
[9]網絡安全:這些是 2023 年需要擔心的新事物: https://www.zdnet.com/article/cybersecurity-these-are-the-new-things-to-worry-about-in-2023/
[10]多種強化 C++ 的: https://www.zdnet.com/article/programming-languages-how-google-is-improving-c-memory-safety/
[11]一項研究: https://langui.sh/2019/07/23/apple-memory-safety/
[12]Microsoft 估計: https://msrc-blog.microsoft.com/2019/07/18/we-need-a-safer-systems-programming-language/
[13]谷歌估計: https://security.googleblog.com/2019/05/queue-hardening-enhancements.html
[14]對被發現廣泛被利用的 0-day 的分析: https://twitter.com/LazyFishBarrel/status/1129000965741404160
[15]Slammer 蠕蟲: https://en.wikipedia.org/wiki/SQL_Slammer
[16]WannaCry: https://www.fireeye.com/blog/threat-research/2017/05/smb-exploited-wannacry-use-of-eternalblue.html
[17]Trident 漏洞: https://blog.lookout.com/trident-pegasus-technical-details
[18]HeartBleed: https://tonyarcieri.com/would-rust-have-prevented-heartbleed-another-look
[19]Android 上的Stagefright: https://googleprojectzero.blogspot.com/2015/09/stagefrightened.html
[20]Ghost漏洞: https://blog.qualys.com/laws-of-vulnerabilities/2015/01/27/the-ghost-vulnerability
[21]醫院: https://www.bbc.com/news/technology-41753022
[22]持不同政見者: https://citizenlab.ca/2016/08/million-dollar-dissident-iphone-zero-day-nso-group-uae/
[23]衛生政策專家: https://citizenlab.ca/2017/02/bittersweet-nso-mexico-spyware/
[24]對社會: https://www.telegraph.co.uk/technology/2018/10/11/wannacry-cyber-attack-cost-nhs-92m-19000-appointments-cancelled/
[25]對您的聲譽: https://www.zdnet.com/article/qualpwn-vulnerabilities-in-qualcomm-chips-let-hackers-compromise-android-devices/
[26]對您的客戶: https://www.nytimes.com/2018/12/02/world/middleeast/saudi-khashoggi-spyware-israel.html
[27]現代 C++ 慣用語: https://alexgaynor.net/2019/apr/21/modern-c++-wont-save-us/
[28]fuzzers: https://llvm.org/docs/LibFuzzer.html
[29]sanitizers: https://clang.llvm.org/docs/AddressSanitizer.html
[30]fuzzers: https://llvm.org/docs/LibFuzzer.html
[31]sanitizers: https://clang.llvm.org/docs/AddressSanitizer.html
[32]利用的漏洞: https://twitter.com/LazyFishBarrel/status/1110021027851964417
[33]每一次成功的攻擊: https://twitter.com/LazyFishBarrel/status/1110023874396078081
[34]WebAuthn: https://blog.mozilla.org/security/2019/03/19/passwordless-web-authentication-support-via-windows-hello/
[35]在 Rust 中編寫 Linux 內核模塊: https://github.com/fishinabarrel/linux-kernel-module-rust
[36]工程副總裁的內存不安全簡介: https://alexgaynor.net/2019/aug/12/introduction-to-memory-unsafety-for-vps-of-engineering/