了解、預防、修復:開源漏洞討論框架
執行摘要
開源軟件的安全性引起了業界關注,這并不奇怪。在實施相關安全方案時,需要對過程中的挑戰與合作達成共識。這個問題很復雜,涉及方方面面:供應鏈、依賴關系管理、身份和構建管道。問題捋清后,解決方案也就呼之欲出。為方便業界討論開源軟件中的漏洞以及首要著眼點,我們提出了一個框架(“了解、預防、修復”),內容包括:
? 元數據和身份標準共識:行業需要就解決這些復雜問題的基本原則達成共識。在元數據細節和身份方面統一看法后,將推動自動化,減少更新軟件所需的工作量,并將漏洞的影響降至最低。
? 提高關鍵軟件的透明度,加強對這些軟件的審查:對于對安全至關重要的軟件,我們需要就開發過程達成一致,確保充分審查,過程透明,避免單方面更改,最終產生語義清晰的可驗證官方版本。
以下框架和目標的提出旨在引發業界對開源軟件安全的討論,促進開源軟件的安全。
鑒于最近發生的多起事件,軟件界切實感受到了供應鏈攻擊的風險實實在在地存在著。開源軟件在安全方面的風險應該較小。因為所有代碼和依賴項都是開放的,可供檢查和驗證。總的來說,這種看法沒什么問題,但它的前提是確實做了檢查。要全面監控這么多的依賴項不太現實,而且許多開源軟件包并沒有得到妥善維護。
一個程序通常直接或間接地依賴于數千個軟件包和庫。例如,Kubernetes現在就有約1000個依賴包。開放源代碼可能比封閉源代碼的依賴關系更多,并且來自更廣泛的供應商;需要信任的實體數量巨大。這樣,就很難弄清楚開放源代碼在產品中的使用情況以及哪些漏洞事關重大,同時也無法保證生成的內容與源代碼匹配。
退一步講,盡管存在供應鏈被攻擊的風險,絕大多數漏洞都是善意的開發人員的無心之失。此外,攻擊者更可能利用已知漏洞,而不是尋找新漏洞:顯然前者更簡單。因此,我們必須集中精力進行根本性的變革,堵住大多數漏洞,進而推動整個行業取得進步,有效解決復雜問題,包括供應鏈攻擊。
很少有組織能夠驗證自己使用的所有軟件包,更不用說這些軟件包的所有更新了。在當前情況下,跟蹤這些包需要大量的基礎設施和大量的手動工作。谷歌擁有這些資源,同時盡自己所能管理所使用的開源軟件包(包括對內部使用的所有開源軟件包建立私有庫),但要跟蹤所有更新仍頗具挑戰。光是上傳下載這些更新就令人望而生畏。無論什么方案,解決這個問題的核心都是提高自動化水平,這將是2021及以后我們開源安全工作的一個重要主題。
由于這個問題很復雜,需要行業合作,本文僅圍繞具體目標展開。谷歌聯合創建了OpenSSF,聚焦于解決這一問題,但要取得進展,需要整個行業的參與,就問題所在以及如何解決這些問題達成一致。為拋磚引玉,我們提出了一個討論辦法以及一系列具體目標,希望通過這些目標加速全行業的解決方案研發。
我們建議將挑戰分為三個基本獨立的問題領域,每一領域都有自己的具體目標:
1. 了解軟件中存在的漏洞
2. 預防新漏洞的出現
3. 修復或刪除漏洞
提高開發過程的安全性是一個相關但獨立的問題,對于確保供應鏈安全至關重要。我們在第四節“關鍵軟件的預防措施”中概述了此問題帶來的挑戰并提出了目標。
了解漏洞
由于各種原因,了解漏洞比想象的要困難。雖然有漏洞報告機制,但很難判斷漏洞是否確實會影響所使用的特定軟件版本。
目標:精確的漏洞數據
首先,從所有可用數據源捕獲精確的漏洞元數據至關重要。例如,知道哪個版本引入了漏洞就能確定所使用的軟件是否受到影響,知道漏洞何時被修復就可以準確及時地進行修補(并減少被利用的可能性)。理想情況下,這種分類工作應自動完成。
其次,大多數漏洞都存在于依賴項中,而不是自己所編寫或控制的代碼中。因此,即使自己的代碼并未改動,漏洞也會不斷發生變化:有被修復的,也有新引入的。
目標:標準的漏洞庫格式
跟蹤和維護開源漏洞、了解其后果并管理緩解措施需要基礎設施和行業標準。采用標準漏洞格式后,通用工具就能跨漏洞庫工作,簡化跟蹤任務,尤其是當漏洞涉及多種語言或子系統時。
目標:精確跟蹤依賴項
要快速了解新漏洞對軟件的影響需要更好的工具,而大型依賴樹的規模和動態特性使這個問題變得愈加棘手。就目前的普遍做法來看,在沒有實際安裝的情況下很難準確預測使用的版本,因為版本解析軟件只能通過安裝程序獲得版本信息。
預防新漏洞
理想的做法是防止漏洞產生。盡管有測試和分析工具可用,預防始終是一個難題。在這里,我們關注兩個具體方面:
? 在決定引入新的依賴項時提前了解風險;
? 改進關鍵軟件的開發過程。
目標:了解新依賴項的風險
第一個方面實際上是指在決定使用某軟件包時提前了解其中存在的漏洞。引入新的依賴項具有內在風險,不能盲目決策。依賴關系一旦引入,會隨著時間的推移越來越難消除。
首要的是要了解漏洞,但這還遠遠不夠。
許多漏洞之所以存在是因為軟件開發過程中未遵守安全最佳實踐。是否所有參與者都使用了雙因素身份認證(2FA)?項目是否有持續集成設置和運行測試?是否集成了模糊測試?這些都是安全檢查類型,可以幫助消費者了解新引入的依賴項中所面臨的風險。得分較低的軟件包需要進一步審查,并制定補救計劃。
OpenSSF最近宣布的安全記分卡項目旨在以全自動方式生成這些數據點。使用記分卡還有助于抵御猖獗的Typosquatting(名稱與常用軟件包相似的惡意軟件包)攻擊,因為這種軟件包的得分要低得多,無法通過多數安全檢查。
改進關鍵軟件的開發過程與漏洞預防相關,但需要進一步討論,所以將在后文詳述。
修復或刪除漏洞
漏洞修復的一般問題不在本文討論之列,我們關注的是管理軟件依賴項漏洞這一具體問題。在這方面,目前幾乎沒有現成工具可用,但隨著漏洞相關數據準確性的提高,可望通過投資新工藝和工具解決這個問題。
當然,最直接的方法是修復漏洞。若采用的是向后兼容方法,那么這一修復會惠及所有人。但問題是,你可能并不具有相關專業知識,也無法直接做出改變。修復漏洞的前提是軟件維護人員知道漏洞的存在并擁有漏洞披露所需的知識和資源。
相反,如果你干脆刪除了包含漏洞的依賴項,這種修復便對自己的軟件以及導入或使用這個軟件的其他人有效,但不會惠及所有人。這一更改由軟件所有者直接控制。
上述場景代表了自己的軟件和漏洞之間依賴關系鏈的兩端,但實際上中間可能存在多個軟件包。人們都指望依賴關系鏈上的某個人能夠修復漏洞。然而,只修復單個環節是不夠的:要更新自己和漏洞之間依賴關系鏈的所有環節,才能修復自己的軟件。每一環節都必須修復之前環節的版本漏洞,這樣才能徹底清除漏洞。因此,更新需要從下到上進行,除非能完全消除依賴項,這個辦法需要勇氣,也幾乎不可能,但若可能的話,則是最佳解決方案。
目標:了解漏洞刪除方案
當前,我們對這一過程缺乏清晰的認識:其他人取得了什么進展,應該在什么級別進行哪些升級?這一過程在哪里受阻?誰負責修復漏洞?誰負責推行修復方案?
目標:利用通知加速修復
最終,依賴項會被修復,之后,就可以在本地升級到新版本。了解修復時間是一個重要目標,因為這可以大大降低漏洞帶來的風險。我們還需要一個通知系統來通告發現的漏洞;通常,新漏洞指新發現的潛在問題,即使實際代碼并沒有更改(例如UNIX實用程序sudo中有一個存在10年之久的漏洞)。對于大型項目,大多數此類問題會出現在間接依賴項中。目前,由于準確性還達不到要求,無法做好通知,但隨著漏洞準確性和元數據(如上所述)的提高,我們還應推動通知。
到目前為止,我們只描述了一種簡單情況:升級都是向后兼容的,這意味著除了沒有漏洞之外,行為相同。
實際上,升級通常不向后兼容,或者受限于限制性版本要求。這些問題意味著更新依賴樹深處的軟件包必然會導致上面的內容發生變化,或者至少要更新要求。常見例子是,修復了最新版本(比如1.3版本),但自己的軟件或中間軟件包要求使用1.2版本。這種情況并不鮮見,如今仍是一大挑戰,尤其是很難讓軟件所有者更新中間軟件包。此外,如果一個軟件包用在一千個不同的地方(這對于大企業來說很正常),那么可能需要經歷一千次更新過程。
目標:修復廣泛使用的版本
修復舊版本中的漏洞也很重要,尤其是那些使用頻繁的版本。這種修復對于具有長期支持的軟件來說很常見,但理想情況下,所有廣泛使用的版本都應該修復,尤其是具有安全風險者。
自動化能促進這項工作:得到某一修復版本后,也許我們可以為其他版本生成有效的修復方案。目前,這個過程有時通過手工完成,但如果我們能大大簡化這一過程,那么實際上能夠修復更多版本,這樣,在依賴關系鏈上端需要做的工作就會減少。
總而言之,我們需要使用多種方法來簡化并加快漏洞修復,尤其是依賴項中的漏洞。對于廣泛使用的版本,需要盡可能進行修復,而不僅僅是修復最新版本,因為最新版本可能包含一些其他程序無法兼容的變更,導致無法采用。
最后,在“修復”方面還有許多其他方案,包括各種緩解措施,如避免某些方法,或通過沙盒或訪問控制抑制風險。這些方案也很重要且可行,需要進一步討論,得到更多支持。
關鍵軟件的預防措施
上述框架廣泛適用于各種漏洞,無論這些漏洞是由惡意主體造成的,還是僅為無心之失。雖然建議的目標涵蓋了大多數漏洞,但它們不足以防止惡意行為。為了加強對惡意行為(包括供應鏈攻擊)的預防,我們需要改進開發過程。
這是一項艱巨的任務,尤其是對于現今大多數的開源軟件而言,很難實現。開源的其中一個優點是對過程沒有限制,這鼓勵了各類人群的廣泛參與。然而,這種靈活性可能會影響安全。我們需要貢獻者,但我們不能指望所有人都對安全給與同樣的關注。我們要做的是識別關鍵軟件包并加以保護。這類關鍵軟件包必須遵守更嚴格的開發標準,即使這會讓開發人員心存抵觸。
目標:定義需要遵循更嚴格標準的“關鍵”開源項目
識別大家普遍依賴的關鍵軟件包很重要,因為這些軟件被入侵后將危及關鍵基礎設施或用戶隱私。關鍵軟件包需要遵循更嚴格的標準,如下所述。
如何定義“關鍵”并非易事,而且定義還可能會隨著時間的推移而擴展。除了OpenSSL或密鑰加密庫等眾所周知的軟件外,還有一些廣泛使用的軟件包,它們的覆蓋范圍之廣決定了它們必須得到保護。我們啟動了關鍵性評分項目,與社區集體討論這個問題,并與哈佛大學合作開展開源普查工作。
目標:避免單方面更改關鍵軟件
谷歌全司遵循的一個原則是,不進行單方更改——也就是說,每個更改都至少涉及一名作者和一名評審者。目標是限制攻擊者獨立行動的能力,保證有人確實查看了變更之處。要在開放源代碼中做到這一點,實際上比在公司內部要困難得多,因為公司能使用強身份認證,強制執行代碼審查和其他檢查。
“避免單方面更改”可拆分為兩個子目標:
目標:要求對關鍵軟件進行代碼審查
審查過程不僅能大大促進代碼改進,還確保除了作者之外,至少有一個人在查看更改。代碼審查是谷歌內部所有變更的標準做法。
目標:關鍵軟件的更改需要獨立兩方的批準
為了真正實現“有人在看”的目標,審查者需要獨立于貢獻者。對于關鍵變更,我們可能需要不止一次獨立審查。當然,我們需要理清“獨立”審查的含義。實際上,獨立審查的理念對于大多數行業來說都很重要。
目標:關鍵軟件參與者認證
獨立意味著參與者身份已知,匿名者則被視為非獨立或可信。現今,基本每個人都有化名:同一個人反復使用同一身份,以此身份為人所知,但我們并不能確定這人一定可信。所以,還需要一系列子目標:
目標:關鍵軟件的所有者和維護者不能匿名
攻擊者喜歡匿名。在之前發生的供應鏈攻擊中,攻擊者利用匿名性,進入軟件包社區成為維護者,但沒人發現這個“新維護者”有惡意意圖(最終向上游注入了入侵源代碼)。我們認為,為了減輕這種風險,關鍵軟件的所有者和維護者不得匿名。
與所有者和維護者不同,貢獻者可以匿名,這可以理解,但前提是他們的代碼通過了可信方的多次審查。
同樣,我們可以擁有“經驗證”的身份,其中一個可信實體知道我們的真實身份,但出于隱私原因,不透露給公眾。這有助于做出關于獨立性的決定,對非法行為進行起訴。
目標:對關鍵軟件貢獻者進行強認證
攻擊者尋找容易利用的攻擊向量,因此釣魚攻擊和與憑據相關的其他形式的盜竊成為常事。要求使用雙因素身份認證,尤其是對于所有者和維護者,這會顯著提升安全。
目標:聯合身份模型
為了繼續保持開放源代碼的包容性,我們需要信任各種身份,但仍然要對完整性進行驗證。這意味著需要采用聯合身份模型,該模型類似于聯合SSL證書支持方式,多個群組可生成有效證書,但具有強大的審核和相互監督機制。
OpenSSF的數字身份認證工作組已開始就此展開討論。
目標:通告風險變化
我們應該擴大通知范圍,對風險變化也進行通知,尤其是所有權變更,這可能是新攻擊的前奏(例如最近發生的NPM事件流入侵)。若發現了被盜憑證、合謀等惡意行為,也說明風險發生了變化。
目標:工件透明度
通常使用安全哈希來檢測所收到的工件是否完好無損,使用數字簽名來證明其真實性。引入“透明度”后,會公開記錄上述驗證及其目的。繼而,外部各方可監控日志,發現連用戶都未覺察的偽造版本。接下來,當憑據被盜時,我們就能篩選出使用這些憑據簽名的工件,將其刪除。這種透明度(包括長期保存的公共日志和第三方監控)已經在SSL證書方面取得了巨大成功。針對軟件包管理器,我們提出了對應的方法。用戶要確認軟件包或二進制文件正確無誤,就好比在訪問網站時要確認網站真實可靠。
目標:信任構建過程
1984年,肯·湯普森(Ken Thompson)在圖靈獎(Turing Award)獲獎感言中做了一個著名的演示,說明僅保證源代碼真實遠遠不夠。近期發生的事件表明,對工件的攻擊已成為了實實在在的威脅。如何保證所構建的系統真實可信?工件的所有組件都必須納入持續的構建信任過程進行驗證,保證可信。
構建若可復制,便能產生確定結果,有助于確認可信性。然而,由于發布工件中存在臨時數據(如時間戳),可復制又很難實現。安全的可復制構建需要驗證工具,而這些工具又必須以可驗證和可復制的方式構建,這樣循環往復。我們必須構造一個可信工具和構建產品網。
工件和工具信任都可以通過“委托”來建立,而委托通過上述透明過程的一個變體實現,稱為二進制授權。谷歌內部的構建系統對所有工件進行簽名,并生成清單,將工件與源代碼關聯起來。對于開放源代碼,一個或多個可信代理可以將構建作為服務運行,對工件進行簽名,證明工件的完整性。這種生態系統應成為現實,在大多數情況下,還需要培養意識,就證明格式達成一致,以便安全地對過程進行自動化。
總體上,本節中的操作對于軟件安全極為有益,如今在谷歌內部廣泛采用。而對于開源來說,這些操作更為重要。我們希望,至少可以針對關鍵軟件實現這些目標。隨著工具和自動化水平的提高,這些目標將會更容易實現,可望普遍推行。
總結
開源的本質要求我們通過共識和協作來解決問題。對于漏洞等復雜主題,需要圍繞關鍵問題進行重點討論。我們為此提出了一種方法,并定義了一組目標,希望通過這些目標促進全行業討論,快速找到最終的解決方案。第一組目標適用于所有漏洞,目的是為了實現自動化,減少風險和工作量。
漏洞管理的一般目標

然而,這些目標尚不足以對抗攻擊者或防止供應鏈攻擊。因此,我們為關鍵軟件提出了第二組目標。這組目標更為繁瑣,因此會遇到一些阻力,但我們認為額外的約束是安全的基礎。目的是定義“關鍵”軟件包,將更嚴格的標準僅應用于這類軟件。
針對關鍵開源軟件的目標

盡管對如何實現這兩組目標看法不一,但在共識和可持續解決方案最為重要的領域,我們意見一致。我們期待大家對此展開討論,互通有無,分享好點子,最終找到解決方案,加強我們所依賴的開放源代碼的安全性,優化防護。