在本月10日,美國國家安全局(NSA)公開發表一份軟體開發指南,是針對軟體記憶體安全(Memory Safety)而來,建議開發者應多使用保障記憶體安全的程式語言,如C#、Rust、Go、Java、Ruby、Swift,以這些來取代C與C++,引起軟體開發界的討論。

事實上,關於C、C++的資安爭論已持續多年,但隨著記憶體安全問題受到越來越大的重視,開發者輕忽指標、記憶體配置的狀況太過普遍,而願意花心力檢測、有足夠經驗處理這類問題的程式設計者太少,而使得軟體資安漏洞層出不窮。

儘管為了降低這方面犯錯的機會,開發界持續宣導C/C++程式設計要重視記憶體管理,有些開發者的確能夠寫出足夠安全的C/C++程式碼,但對大多數程式設計師來說,卻可能並非易事,有些科技業者祭出記憶體安全機制來因應,但多年下來,犯錯比例仍是居高不下,大大降低了安全性、穩定性與生產力。這也使得另一條因應路線被持續探討,也就是多使用具記憶體安全特性的程式語言,如此一來,即便是資安意識不足的開發人員,也因為開發環境的局限,而不用擔心記憶體管理的問題,可以儘管放心去配置所需的記憶體空間,減少犯錯的機會。而且,如今這類軟體開發安全措施的推動態勢,也從一些科技大廠而開始擴及國家政府機構。

多數軟體漏洞可歸咎於記憶體安全性不足

在今年5月,我們看到開源社群、科技大廠與美政府二度商討開源軟體安全對策,會後Linux基金會與開源安全基金會(OpenSSF)發布的開源軟體安全動員計畫白皮書中,替換不具記憶體安全(non-memory-safe)的程式語言,就是十大對策之一,並預計前兩年針對這方面投入經費550萬美元。

到了11月,美國NSA也對此公開表態。針對軟體記憶體安全問題,他們建議各組織在可能情況下,對於程式語言的採用,應考慮做出戰略性的轉變,從不具記憶體保護的C/C++,轉而使用具記憶體安全的其他程式語言,例如C#、Go、Java、Ruby與Swift等。

在這份公開文件中,NSA首先強調軟體記憶體安全的重要性,指出雖然開發人員經常進行嚴格測試,為軟體中的邏輯準備好應對意外情況,然而,各種可濫用的軟體漏洞,仍經常是基於記憶體問題而成。例如:記憶體緩衝區溢位,以及管理記憶體失當而導致的洩漏問題。

最近幾年已有更多這方面的研究,例如,微軟在2019年曾公開提出自我檢討,他們表示,在2006年到2018年間的安全漏洞,有70%源自記憶體的安全問題,Google在2020年也針對自家發展的瀏覽器Chrome提出檢討,當中也存在同樣高比例的記憶體安全漏洞。由於存在規模如此龐大的軟體開發缺失,駭客可利用這些漏洞來執行遠端程式攻擊,作為大舉入侵組織網路的第一步。

而在程式語言中,現今應用範圍最大且最常見的C與C++,方便之餘,多年來大家也經常詬病其安全性管制太少,而使得記憶體類型的漏洞總是無法徹底根絕。事實上,這兩種語言在記憶體管理上,提供了很大的自由度與彈性,相對地,用這些語言所開發的應用程式,其安全性將高度依賴開發者的處理方式,例如,是否對記憶體參照執行必要的檢查與驗證。因此,可能只要出現一個簡單的錯誤、疏忽,就會導致記憶體遭濫用的安全漏洞。

固然我們可以透過軟體分析工具偵測出許多記憶體管理問題,透過作業系統環境本身內建的機制,也能帶來某些程度的保護,但NSA認為,若能藉由已內建記憶體保護的程式語言來撰寫程式,即可避免或減少絕大多數的記憶體管理問題。

緩衝區溢位、管理不當,均是常見記憶體安全問題

記憶體安全,也就是有關於程式如何管理記憶體的一大類問題。這當中有哪些常見問題?

NSA指出,記憶體「緩衝區溢位」(buffer overflow)就是一例,也就是資料的存取意外超出緩衝區邊界(outside the bounds),另一個常見的安全問題則與記憶體分配有關。

簡單來說,系統程式在執行時可以分配所需新的記憶體位置,然後在不需要記憶體時,將其取消分配,此舉稱為釋放記憶體,但如果開發者不小心這麼做,新的記憶體可能會在程式執行過程中被重複分配,因此,記憶體並非總是在不再需要時被釋放,進而出現記憶體洩漏(memory leak)的問題,最終甚至導致可用的記憶體資源被使用殆盡。

此外,也有因邏輯錯誤而出現記憶體存取不安全的狀況。因為這樣的問題,程式可能試圖使用已經被釋放的記憶體,甚至重複釋放原本已被釋放的記憶體。例如,當程式語言允許使用尚未初始化的變數時,就會出現另一個問題,導致該變數使用之前在記憶體中該位置設置的值。

另一個值得注意的問題,則是條件競爭(Race condition)。例如,當程式存取相同資料,此時若出現兩個操作順序,可能會因此影響程式的結果,而發生這個問題。NSA強調,所有這些記憶體問題都是相當常見的現象。

而且,記憶體管理問題衍生安全漏洞只是其中一種類型的狀況,就算是不會遭到濫用的記憶體,也可能因為一些疏失而造成錯誤的程式結果,例如,降低執行效能或軟體本身無法執行。

針對上述種種軟體記憶體安全的問題,NSA指出,採用能夠自動管理記憶體的程式語言,像是C#、Rust、Go、Java、Ruby、Swift等,可協助避免開發者陷入某些類型的記憶體問題,以預防無意採用錯誤的記憶體管理方式。

但NSA也提醒,他們強調,就算是使用這些內建記憶體保護的程式語言,也並非毫無風險,因為軟體有時仍需要執行不安全的記憶體管理功能,才能完成任務,而且,各種程式語言對記憶體的安全保護程度不一,因此不能單靠更換程式語言而確保軟體安全。換言之,具記憶體安全的其他程式語言,其實一樣容易受到攻擊,因此都需要積極採取措施持續增加安全性。

另一方面,對於無法立即轉向採用內建記憶體安全的程式語言的開發者,NSA建議,應透過安全測試來強化應用程式的安全性,包括進行靜態(SAST)與動態(DAST)的安全測試,而且最好是執行多個SAST及DAST工具,以提高找出記憶體問題的機率,確保應用程式的安全。儘管這可能會增加大量的工作負擔,卻可以帶來更安全的程式碼。

總之,NSA鼓勵組織儘可能採取多管齊下的方式,來強化記憶體管理的安全性。除了採用記憶體安全程式語言,還可同時輔以編譯器選項、工具分析及作業系統配置,以減少記憶體漏洞,提高駭客的攻擊門檻。

今年出現Prossimo專案,開始推動安全程式語言的廣泛採用

對於NSA的這項建議,根據IT新聞媒體The Register的報導,Acronis資安長Kevin Reed認為,NSA正在做正確的事情,但他懷疑這是否會有立竿見影的效果,因為多年來使用C/C++撰寫的程式碼數量龐大,即便明天就開始改用Rust與Go,也需要幾十年才能清理這個爛攤子。

而且,真的能夠如此順利推動嗎?微軟Azure技術長Mark Russinovich在今年9月就曾針對這樣的議題,於社群媒體推特發表了看法。他指出,在安全性與可靠性考量下,現在該停用C/C++開發任何新專案,並建議改用Rust。但在此則貼文回應中,有相當多開發者持反對意見,畢竟C與C++仍是熱門程式語言。

但無論如何,記憶體安全問題已不容忽視。對照MITRE公布的2022年25大常見CWE通用弱點列表名單,我們可以發現,記憶體越界寫入(Out of Bounds Writes),記憶體越界讀取(Out of Bounds Reads),以及使用已釋放的記憶體(Use after Free),都在前七名內,尤其是記憶體越界寫入,持續居於第一嚴重的地位,而這樣居高不下的排名,也呼應多數軟體漏洞可直接歸因於缺乏記憶體安全性的推論。

而在今年5月Linux基金會與OpenSSF發布的「開源軟體安全動員計畫」白皮書中,其實已經針對此問題提出對策,此計畫的主要目標,是減少記憶體安全性漏洞的數量。

首先,他們希望,在網際網路上最關鍵的軟體,能夠遠離C/C++等不安全的程式語言,並強調會優先升級對安全最敏感的元件,其次,系統級程式碼的工具需要受到更大的關注,因為這些是生態系統中最普遍與最脆弱的軟體,也最有可能是以不安全的系統程式語言所寫成,而產生了資安漏洞。

同時,這項戰略的執行,將透過非營利組織網際網路安全小組(ISRG)的Prossimo專案來推動。目前這項計畫倡議有那些面向?例如,針對用C語言撰寫的Linux Kernel,如今已有Rust for Linux專案啟動,並指出初期Rust程式碼已合併到Linux Kernel,且這只是一個開始;針對用C語言撰寫的OpenSSL,在替代方案上,也有一套名為Rustls的開放軟體專案正在發展。其餘面向還包括:網路時間協定NTP、Apache httpd的mod_tls模組、Trust-DNS、網路傳輸程式curl,同時,Prossimo專案將針對相關工具進行投資,目的是讓建構更安全軟體變得簡單。

而在這些消息中,我們可以發現支持採用Rust的聲浪最大,而且,許多大型企業與開源專案也都嘗試用Rust來撰寫,像是Google的Android與Chrome、Amazon的虛擬化技術Firecracker等。

無論如何,因應軟體開發造成的記憶體安全性問題,已不只是口頭呼籲,而是有所行動,再加入美國NSA難得表態力挺使用安全程式語言,使得這項一再受到討論與思考的問題,出現了更多大幅改善的機會。文⊙羅正漢、陳曉莉

根據Wikipedia上對於Stack buffer overflow的說明,當中也特別以圖像化方式表達緩衝區溢位的攻擊利用方式。

根據MITRE在今年8月3日公布的2022年25大常見CWE通用弱點列表名單(2022 CWE Top 25 Most Dangerous Software Weaknesses),我們可以看出在漏洞根因中,記憶體越界寫入(Out of Bounds Writes)居於第一,且指標分數高達64.20,記憶體越界讀取(Out of Bounds Reads)居第五,使用已釋放的記憶體(Use after Free)居第七。

2019年2月7日 微軟MSRC研究人員Matt Miller在BlueHat IL資安會議的演講中表示,從2006年到2018年間,每一年發布的漏洞修補更新,有70%是與記憶體安全問題有關。

2020年5月16日 Chromium專案研究人員指出,此項軟體有超過70%的嚴重安全漏洞來自記憶體安全漏洞,也就是因C/C++指標操作錯誤所造成,其中一半的錯誤是釋放後使用(Use-After-Free)的問題。

2022年5月13日 為了解決開源軟體安全問題,開源社群、科技大廠與美政府二度商討對策,會後發布「開源軟體安全動員計畫」白皮書,針對10大關鍵挑戰提出投資戰略,當中1項就是聚焦於替換不具記憶體安全的程式語言。

2022年9月20日 微軟Azure技術長Mark Russinovich在推特發文表示,在安全性與可靠性考量下,現在應停用C/C++開發新專案,建議改用Rust。但許多開發者表示反對,因為C與C++畢竟是熱門程式語言。

2022年10月4日 以洋蔥路由聞名的開源軟體專案Tor,釋出以Rust重新實作的版本時表示,在2001年用C語言是合理選擇,但他們發現安全使用C語言需付出許多心力,程式碼分析與安全性改進也變得越來越困難。

2022年11月10日 美國NSA公開發表防範軟體記憶體安全問題的軟體開發指南,建議開發人員使用保障記憶體安全的程式語言,例如:C#、Rust、Go、Java、Ruby或Swift,以取代C與C++。

對於蘋果作業系統與記憶體安全的議題,也有研究人員致力這方面的研究,他檢視iOS/IPadOS,以及macOS,針對2020年推出的iOS/IPadOS 14版本而言,指出60%以上漏洞與記憶體安全問題有關。

儘管Rust受注目,但大家可能也要有正確的認知,例如,Rust基金會在今年9月13日一篇文章中,其執行董事Bec Rumbul提到,外界對於Rust普遍有所誤解,認為Rust是一種記憶體安全的程式語言,因此具100%安全性,但事實上,Rust也與其他程式語言一樣容易受到攻擊,因此需要採取積極措施,持續增加安全性。

因應記憶體安全(Memory Safety)問題,不再只是呼籲口號,根據「開源軟體安全動員計畫」白皮書指出,已有非營利組織網際網路安全小組(ISRG)的Prossimo專案負責推動相關工作,當中建議使用Rust、Go、C#、java、Swift、Python與JavaScript等語言,來取代使用不具記憶體安全的C、C++與assembly。該專案網站:https://www.memorysafety.org/

繼續閱讀:Android記憶體安全漏洞數量大幅下降,Rust程式碼比例上升成關鍵

熱門新聞

Advertisement