一、摘要
開源軟件的安全問題理所當然地引起了業界的關注,但解決方案需要對執行過程中的挑戰和合作達成共識。這個問題很復雜,涉及諸多方面:供應鏈、依賴庫管理、身份識別和構建流水線(build pipelines)。如果能夠準確定義問題,便可更快得出解決方案;為此,我們提出了一個框架(“知悉、預防、修復”),該框架是關于行業內應當如何考慮開源軟件中的漏洞,并列舉了需要首先解決的具體問題,包括:
就元數據和身份識別標準達成共識。我們需要在基本面上達成一致來解決這些行業復雜問題。就元數據細節和身份識別達成的共識將有助于實現自動化,減少更新軟件所需的工作量,并將漏洞的影響最小化。
提高關鍵軟件的透明度并加強代碼審查。對于安全關鍵性軟件,我們需要就開發流程達成一致意見,確保充分的審查,避免單方面變更,并透明公開地生成定義明確、可被驗證的正式版本。
下面提出的框架和目標,旨在引發全行業對開源軟件的安全問題進行探討并尋求進步。
由于近期發生的事件,軟件界對供應鏈攻擊的實際風險有了更加深刻的了解。因為全部代碼和依賴關系都公開可查驗,開源軟件在安全方面的風險相對較小。一般來講確實如此,但前提是人們真的有在查驗。由于依賴關系眾多,要監控所有這些依賴并不切實際,而且很多開源包并沒有得到很好的維護。
程序通常直接或間接地依賴于數千個軟件包和庫。舉例來說,Kubernetes現在依賴大約1000個軟件包。與閉源軟件相比,開源軟件使用了更多的依賴庫,并且供應商來源更加廣泛;因此需要信任相當多的不同實體。這使得理解產品如何使用開源軟件以及如何發現相關漏洞是極其困難的。此外,沒有辦法可以保證構建出的程序與其源代碼相匹配。
退一步來講,雖然供應鏈攻擊是一種風險,但絕大多數漏洞都是普通的、無意的--善意的開發者所犯的無心之過。此外,相較于親自發現漏洞,惡意攻擊者更傾向于利用已知漏洞,原因很簡單:因為這會使得攻擊更加容易。因此,我們必須集中精力做出根本性改變以解決大部分漏洞,唯有這樣做才會使整個行業得以深入解決那些復雜問題(包括供應鏈攻擊)。
幾乎沒有任何組織能夠驗證他們使用的所有程序包,更不用說這些包的更新了。就目前而言,跟蹤這些軟件包需要耗費大量的基礎設施和顯著的人力開銷。我們在Google擁有這些資源,并不遺余力管理我們使用的開源包--包括為我們內部使用的所有開源包維護一個私有倉庫--但想要跟蹤全部的更新仍然困難重重。龐大的更新流令人望而生畏。所有解決方案的核心部分都是更高程度的自動化,這將是2021年及以后我們開源安全工作的關鍵主題。
因為這是一個需要行業合作的復雜問題,所以我們目的是圍繞具體的目標展開對話。Google聯合創立了OpenSSF并將其作為此次合作的重點。但是為了更進一步,我們需要整個行業參與進來,并就問題所在以及如何解決問題達成共識。作為開始,我們提出了解決此問題的一種方法,以及一系列具體的目標,希望這些目標可以加速產生整個行業的解決方案。
我們建議將這一挑戰定義為三個基本獨立的問題領域,每個領域都有具體的目標。
知悉軟件中的漏洞
預防新漏洞的產生
修復或消除漏洞
另一個相關但獨立的問題是提高開發過程的安全性,這對保障供應鏈的安全至關重要。我們將在第四節“關鍵軟件的預防措施”中概述該問題所面臨的挑戰并提出目標。
二、知悉已有漏洞
由于各種原因,知悉已有漏洞遠比預期來的更困難。盡管存在漏洞報告機制,但很難確認軟件的特定版本是否受到漏洞影響。
1. 目標:獲得準確的漏洞數據
首先,從所有可用的數據來源中準確獲取漏洞元數據至關重要。例如,知悉哪個版本引入了漏洞,將有助于判斷某個軟件是否受影響;而知悉何時漏洞被修復,就能準確及時地打補?。úp少潛在的漏洞利用窗口期)。理想情況下,這種分流工作流程應當自動化完成。
其次,大多數漏洞都存在于依賴庫中,而不是在你直接編寫或控制的代碼中。因此,即使你的代碼沒有改動,漏洞也會不斷地出現,此消彼長。
2. 目標:建立漏洞數據庫的標準架構
需要建立基礎設施和行業標準來跟蹤和維護開源漏洞、了解漏洞產生的后果并管理緩解措施。標準的漏洞架構將允許通用工具跨多個漏洞數據庫工作并簡化跟蹤任務,特別是當漏洞涉及多種語言或子系統時。
3. 目標:準確跟蹤依賴關系
我們需要更好的工具來快速了解哪些軟件受到新發現漏洞的影響,而依賴樹的巨大規模和動態特性使這一問題變得更加棘手。由于只有通過安裝程序才能解析出軟件的版本,因此如果不實際進行安裝操作,當前也很難有辦法準確地預測出被調用的軟件版本。
三、預防新增漏洞
理想的做法是預防漏洞的產生,盡管測試和分析工具有所幫助,但預防始終是一個難題。在這里,我們著重討論兩個特定方面。
決定采用新的依賴庫時需要理解風險。
改進安全關鍵性軟件(security-critical software)的開發流程。
1. 目標:理解新依賴庫的風險
第一個方面主要是:當你決定使用一個軟件包的時候,需要了解它的漏洞。接受一個新的依賴庫會帶來固有風險,因此需要做出明智的決定。一旦使用了依賴庫,隨著時間的推移通常會變得越來越難以移除。了解漏洞是一個不錯的開始,但我們還可以更進一步。
理想情況下,如果沒有顯式更新的情況,依賴庫的版本應該是穩定的,但具體的行為因打包系統而異。Go Modules和NuGet這兩個打包系統都以穩定為目標,而不追求快速升級,默認情況下它們都只在需求項更新時才會安裝升級程序;依賴關系可能有誤,但它們只在顯式更新時才會去修改。
許多漏洞是由于在軟件開發過程中沒有遵守安全最佳實踐而產生的。所有的貢獻者是否都使用了雙因素認證(2FA)?項目是否設置了持續集成并運行測試?是否集成了模糊測試?這些類型的安全檢查將幫助使用者了解新依賴庫帶來的風險。對于“得分”較低的軟件包需要仔細審查,并制定風險緩解計劃。
OpenSSF最近公布的“安全記分卡”(Security Scorecards)項目嘗試以全自動的方式生成這些數據。使用記分卡還可以幫助抵御猖獗的名稱仿冒(Typosquatting)攻擊(惡意軟件包采用與流行軟件包相似的名稱),因為仿冒的惡意軟件包得分會很低,并且無法通過很多安全檢查。
改進關鍵軟件的開發流程不僅僅與漏洞預防相關,我們將在后續章節中進一步討論。
四、修復或消除漏洞
傳統意義上的修復漏洞問題超出了我們的討論范圍,但對于管理軟件依賴庫中的漏洞這一具體問題,需要我們做的還有很多。雖然現在沒什么幫助,但隨著我們提高準確度,有必要對新的流程和工具進行投資。
當然,一種選擇是直接修復漏洞。如果你能通過向后兼容的方式完成修復,那么該修復程序就可以為大家所用。但面臨的挑戰是,你不太可能擁有關于這個漏洞的專業知識,也沒有辦法直接進行修改。修復漏洞的前提是軟件維護者意識到問題,并且公開漏洞相關的知識和資源。
相反,如果你只是簡單移除包含漏洞的依賴庫,那么對于你和那些導入或使用你軟件的人來說漏洞被修復了,但對其他人則沒有。這是一個可由你直接控制的變更。
上述場景描述的是你的軟件與漏洞分別位于依賴關系鏈的兩端,但在實踐中可能還會存在許多其他關聯軟件包。大家普遍寄希望于依賴鏈上的某個人來修復它。不幸的是,僅修復一個環節是遠遠不夠的。只有你和漏洞之間依賴鏈中的每一個環節都更新完畢后,你的軟件才算被修復。每一個環節都必須引用其依賴鏈以下軟件包的已修復版本來清除漏洞。因此,更新需要自下而上地進行,除非你能完全消除依賴關系(這或許需要類似的英雄膽識,而且幾乎不可能發生——但在可能的情況下,這其實是最好的解決方案)。
1. 目標:了解消除漏洞的可選方案
時至今日,我們對這一過程仍缺乏清晰認知:別人已經取得了哪些進展?應該在哪個層面上應用哪個升級程序?這個過程又卡在哪里?誰來負責修復漏洞本身?誰來負責傳播修復程序?
2. 目標:快速修復通知
最終而言,你的依賴庫漏洞將被修復,你可以在本地升級到新版本。但重要的是搞清楚這件事何時會發生,因為它可以快速減少漏洞的暴露風險。此外,我們還需要一個漏洞發現通知系統;通常來說,新漏洞往往意味著新發現了潛伏的問題,即使實際代碼并未改動(比如Unix實用程序sudo漏洞已有10年的歷史)。對于大型項目來說,大多數這樣的問題出現于間接依賴庫中。如今,我們還缺乏做好通知系統所需的準確度,因此在我們提高漏洞準確度和改進元數據(如上文所述)的同時,我們也應該推動通知系統的進步。
目前為止,我們僅描述了一種簡單情形:一連串向后兼容的升級,這意味著除了漏洞被消除之外,行為沒有區別。
但實際上,升級往往并不向后兼容,或者被版本限制要求所阻礙。這些問題意味著更新依賴樹深處的軟件包必然會在依賴鏈上層引起一些混亂,或者至少會導致需求項更新。這種情況通常出現在最新版本(比如說1.3版)有了更新程序,但你的軟件或相關的包需要引用1.2版時。這種情況司空見慣,成為一項重大挑戰,由于很難讓開源項目的所有者更新相關的包,因此變得更加艱巨。此外,如果你在成百上千處使用了某個軟件包(這對于大型企業來說并不瘋狂),那么你可能需要經歷成百上千次更新過程。
3. 目標:修復廣泛使用的版本
修復舊版本中的漏洞同樣重要,尤其是那些使用頻繁的版本。這種修復方式常見于那些擁有長期支持的軟件中,但在理想情況下,所有廣泛使用的版本都應該被修復,特別是包含安全風險的版本。
自動化方法可能會有所幫助:給定某個版本的修復代碼,或許我們可以為其他版本自動生成良好的備選修復代碼。目前這個過程有時是手工完成的,但如果此過程被大大簡化,我們就能修復更多的版本,減少依賴鏈更高層的工作。
綜上所述,我們需要更便捷且更及時地修復漏洞,尤其是依賴庫中的漏洞。不僅是最新版本,廣泛使用的版本也需要獲得更多修復的機會,因為最新版本通常包含有其他變更,所以很難被采用。
最后,在“修復”方面還有很多其他選擇,包括各種緩解措施,比如避免調用特定方法,或者通過沙箱或訪問控制來限制風險。這些都是重要且可行的備選方案,理應得到更多的討論和支持。
五、關鍵軟件的預防措施
上述框架廣泛適用于各種漏洞,無論是惡意攻擊者蓄意造成的,或者僅僅是無心之過。雖然前面建議的目標涵蓋了大多數漏洞,但僅靠這些并不足以防止惡意行為。為了對預防惡意攻擊者(包括供應鏈攻擊)做出實質性改變,我們需要改進開發流程。
這是一項艱巨的任務,并且目前對于大多數的開源項目來說都不切實際。開源之美某種意義上來說是由于缺少流程的約束,因此吸引了廣泛的貢獻者。然而,這種靈活性會阻礙安全方面的考慮。我們需要貢獻者,但我們不能寄希望于每個人都同樣關注安全問題。相反,我們必須確定關鍵軟件包并加以保護。盡管可能會增加開發人員之間的摩擦,但這些關鍵包必須遵循一系列更嚴格的開發標準。
1. 目標:定義符合更高標準的“關鍵”開源項目的評判準則
確定廣泛被依賴的“關鍵”軟件包至關重要,若失陷會危及關鍵基礎設施或用戶隱私。因此這些軟件包必須遵循更高的標準,我們在下文中概述了其中一些標準。
如何定義“關鍵”的標準并不明確,隨著時間的推移,定義的范圍可能還會擴大。除了顯而易見的軟件,如OpenSSL或密鑰加密庫,還有一些被廣泛使用的軟件包,其覆蓋面之廣使它們值得受到保護。Google啟動了關鍵性得分項目(Criticality Score project),與社區一起對該問題集思廣益,同時與哈佛大學合作開展開源普查(Open Source Census)工作。
2. 目標:禁止對關鍵軟件進行任何單方面變更
我們在Google中遵循的一個原則是,變更不應該是單方面的--也就是說,每一個變更都至少涉及一個作者和一個審核者/批準者。目標是限制對手可以憑借一己之力做的事情--我們需要確保有人真正在檢查這些變更。對于開源項目來說,要做好這一點其實比在一家公司內部要難得多,因為公司內部擁有嚴格的身份認證,并且會執行代碼審查和其他檢查。
避免單方面變更可以分為兩個子目標。
(1) 目標:要求對關鍵軟件進行代碼審查。
代碼審查不僅是改進代碼的好方法,還能確保除了作者之外,至少有一個人在檢查每一項變更。代碼審查是Google內部所有變更的標準做法。
(2) 目標:對關鍵軟件的變更需要得到兩個獨立方的批準。
為了真正實現“有人在檢查”的目標,我們需要審查者獨立于代碼貢獻者。而對于重大變更,我們可能需要不止一個獨立審查。當然,我們需要理清到底什么才算是“獨立”審查,但對大多數行業內的審查而言,獨立性思想都至關重要。
3. 目標:對關鍵軟件參與者進行身份認證
獨立性的概念通常意味著你了解參與者——匿名參與者不能被認為是獨立的或值得信賴的。時至今日,我們基本上都使用化名:同一個人反復使用同一個身份,從而積攢聲譽,但我們并不了解這個人是否可信。這就引出了一系列的子目標。
(1) 目標:對于關鍵軟件,所有者和維護者不能匿名。
攻擊者都喜歡匿名。在過去的供應鏈攻擊中,攻擊者利用匿名性,通過軟件包社區努力成為維護者,而沒有人意識到這個“新的維護者”具有惡意企圖(入侵代碼最終被注入上游)。為了減輕這種風險,我們認為關鍵軟件的所有者和維護者一定不能匿名。
可以想見,與所有者和維護者不同,貢獻者可以匿名,但前提是他們的代碼已經通過了可信人士的多次審查。
也可以想見,我們可以擁有“已驗證”的身份,也就是說:有一個可信實體知悉他的真實身份,但出于隱私原因,公眾并不知道。這將有助于有關獨立性的決策以及對非法行為進行起訴。
(2) 目標:為關鍵軟件的貢獻者提供嚴格的身份認證。
惡意攻擊者會尋找容易的攻擊載體,所以網絡釣魚攻擊和其他形式的憑證盜竊行為很常見。一個顯而易見的改進措施是要求使用雙因子認證,尤其是對于所有者和維護者。
(3) 目標:身份的聯合模型
為了繼續保持開源的包容性,我們需要能夠信任各式各樣的身份,但是可驗證的完整性仍不可或缺。這意味著身份的聯合模型,也許類似于我們今天支持聯合SSL證書的方式——多個團體可以生成有效的證書,但必須具備嚴格的審計和相互監督。
OpenSSF的數字身份認證工作組已經開始對該話題進行討論。
(4) 目標:風險變化通知
為涵蓋風險的變化,我們應當擴大通知的范圍。最明顯的是所有權變化,這可能是新攻擊的前奏(如最近的NPM事件流(NPM event-stream)失陷)。其他例子包括發現憑證被盜、串通或其他惡意行為者的行為。
(5) 目標:增加構件的透明度
通常使用安全散列來檢測構件(artifact)是否完好無損,使用數字簽名來證明真實性。增加“透明度”意味著這些證明會被公開記錄,從而將所有意圖文檔化。反過來,即使用戶沒有感知,外部各方也可以監控日志中是否存在偽造版本。更進一步來說,當憑證被盜時,我們可以了解到這些憑證被用來簽署了哪些構件,并可以設法刪除它們。這種透明性,包括持久的公共日志和第三方監控,已被成功應用于SSL證書,我們也為包管理器提出了一種類似方法。知悉你使用了正確的軟件包或二進制文件,類似于知悉你正在訪問一個網站的真實版本一樣。
(6) 目標:信任構建過程
1984年,肯-湯普森著名的圖靈獎演講證明了僅靠真實可信的源代碼還遠遠不夠,最近的事件表明構建過程攻擊也是一種真正的威脅。如何確認你的構建系統是可信的?它的所有組件都必須可信,并通過一個持續的建立信任的過程來驗證。
可重復構建(Reproducible builds)會有所幫助(構建具有確定的結果,由此我們可以驗證我們的構建是正確的),但由于臨時的數據(如時間戳)最終會出現在構建的發行版中,因此這很難實現。而安全可重復的構建需要驗證工具,而驗證工具又必須經過可驗證和可重復的構建,以此類推。我們必須打造一個可信工具和構建產品的網絡。
對構件和工具的信任都可以通過“委托”(上述透明過程的變體,被稱為二進制授權)來建立。在Google內部,構建系統會對所有構件進行簽名,并生成與源代碼相關聯的清單。對于開源項目來說,一個或多個受信任的代理可以將構建作為一項服務來運行,對構件簽名以證明他們對其完整性負責。這種生態系統理應存在,大部分情況下只需要大家都意識到這一點,并按照證明文書格式簽署一些協議,我們就可以安全地自動化上述流程。
本節所述的措施非常適合于一般性的軟件,目前在Google內部已廣泛使用,但是對于開源項目來說,它們的工作量要大得多。我們期望通過專注于少數關鍵的軟件,至少在關鍵軟件上實現這些目標。隨著工具和自動化程度的提高,這些目標將更容易被廣泛采用。
六、總結
開源的本質要求我們通過共識和協作來解決問題。對于漏洞等復雜主題,這意味著要圍繞關鍵問題進行集中討論。我們為這種討論提出了一種框架方法,并定義了一系列目標,我們希望這些目標能夠加速整個行業的討論并得出最終的解決方案。第一組目標廣泛適用于各種漏洞,其實質是關于實現自動化,減少風險和辛勞。
責編AJX
-
谷歌
+關注
關注
27文章
6161瀏覽量
105300 -
軟件
+關注
關注
69文章
4921瀏覽量
87396 -
框架
+關注
關注
0文章
403瀏覽量
17475 -
開源
+關注
關注
3文章
3309瀏覽量
42471
發布評論請先 登錄
相關推薦
評論