為什么代碼重用仍然是一個安全噩夢
現代軟件應用程序是由數以千計的從公共資源庫中獲取的第三方組件拼接而成的。這種代碼的重用對軟件行業有很大的好處,它減少了開發時間和成本,使開發人員能夠更快地增加功能,但由于復雜的依賴關系系統往往難以跟蹤,它也產生了重大的漏洞管理問題。
繼承自第三方代碼的漏洞多年來一直困擾著應用程序,但在政府贊助的軟件供應鏈攻擊時代,這個問題比以往任何時候都更有意義。軟件組合分析工具可以幫助發現其中的一些風險,但微妙的依賴性盲點仍然存在,即使是有安全意識的開發人員也很難抓住所有繼承的缺陷。
來自ReversingLabs的安全研究人員最近對NuGet倉庫進行了掃描,發現有5萬個軟件包正在使用一個名為zlib的流行庫的過時和脆弱版本。他們中的許多人沒有明確地把它列為依賴關系。
依賴性跟蹤是一針見血的
為了發現所有的漏洞,開發人員不僅需要跟蹤他們在自己的應用程序中使用的組件,還需要跟蹤這些組件所基于的第三方庫和包。依賴關系鏈可以深入很多層。達姆施塔特大學的研究人員在2019年對npm資源庫進行的分析發現,平均來說,導入一個JavaScript包會對39個不同維護者的79個其他包引入隱性信任。當時,研究人員還發現,近40%的軟件包依賴的代碼至少有一個公開的漏洞。
一個問題是,只有與同一存儲庫上的軟件包有關的依賴關系才會被軟件包存儲庫及其相應的軟件包管理工具所追蹤。但這并不是第三方代碼進入項目的唯一途徑。一些開發者靜態鏈接庫或手動編譯來自其他項目的代碼,這些代碼存在于軟件包庫之外,這些信息不容易用自動掃描工具找到。
ReversingLabs發現超過50個NuGet軟件包包含主動利用的漏洞,因為它們捆綁了過時的和脆弱的7Zip、WinSCP和PuTTYgen版本。這些都是流行的壓縮或網絡連接程序,它們不直接托管在NuGet上,但可能有其他開發者在NuGet上為它們創建的包裝包。
NuGet是.NET編程語言的主要倉庫,那里托管的大多數組件都是以ZIP檔案的形式發送,擴展名為.nupkg,包含預編譯的Windows .DLL庫,旨在導入其他軟件項目中。
ReversingLabs發現的一個易受攻擊的NuGet包名為WinSCPHelper,是WinSCP的一個封裝庫。它允許集成它的應用程序通過SFTP協議管理遠程服務器上的文件。WinSCPHelper自2017年以來沒有在NuGet上更新過,但最后一個版本自發布以來被下載了超過34000次,在過去6周內被下載了約700次。最新的WinSCP版本是5.17.10,包含一個關鍵的遠程代碼執行漏洞的補丁,但與WinSCPHelper捆綁的版本是一個更老的版本--5.11.2。
"雖然在這種情況下,被分析的軟件包明確指出它使用了WinSCP,但它沒有在依賴列表中披露版本,你不能輕易發現哪些漏洞影響了它的基礎依賴,"研究人員說。"這是手工作業,仍然可以做到,但需要一些努力"。
識別無聲的漏洞
但追蹤依賴關系可能比這更難。以zlib為例,它是最廣泛使用的開源數據壓縮庫之一,最初寫于1995年。這個庫幾乎已經成為事實上的標準,并由其維護者作為源代碼提供。這意味著開發人員傾向于自己編譯它,并在他們的項目中靜態地鏈接它,由于它是如此無處不在,所以常常不提它的存在。
通過靜態文件分析,ReversingLabs發現超過5萬個NuGet軟件包使用zlib 1.2.8版本,該版本發布于2013年,包含四個高度或嚴重的漏洞。一些被識別的軟件包通過其他沒有明確列出依賴關系的第三方組件繼承了這個舊的zlib版本和它的漏洞,促使研究人員把這些稱為沉默的漏洞。
ReversingLabs提供的一個例子是一個名為DicomObjects的NuGet包,它實現了醫學中的數字成像和通信(DICOM)協議。DICOM是一個用于傳輸和管理醫學成像數據的標準。它在醫院中被廣泛使用,并被許多成像設備支持,如醫療掃描儀、打印機、服務器和工作站。
DicomObjects被醫療軟件開發者用來輕松構建DICOM解決方案,它有近54000次下載,由一家名為Medical Connections的英國公司維護。該軟件包將Microsoft.AspNet.WebApi.Client、Newtonsoft.Json和System.Net.Http列為依賴項,但據ReversingLabs稱,它還捆綁了一個名為ceTe.DynamicPDF.Viewer.40.x86.dll的商業PDF庫,但沒有明確提及。DynamicPDF Viewer在NuGet上被列為一個單獨的軟件包,但DicomObjects中捆綁的版本是一個更老的版本,包括zlib 1.2.8。
"這是最常見的軟件維護問題之一,"研究人員說。"開發者創建了一個軟件包,決定使用第三方軟件,但在隨后的更新過程中,依賴性被忽略了。在這種情況下,事情就更糟糕了,因為任何地方都沒有明確提到DicomObjects軟件包依賴于DynamicPDF.Viewer。我們沒有辦法知道DynamicPDF.Viewer依賴于有漏洞的zlib庫。以這種方式堆疊隱藏的依賴關系會導致多層次的無聲漏洞,并使軟件維護和審計的難度大大增加"。
Medical Connections沒有立即回應評論請求。
另一個例子是一個叫做librdkafka.redist的高度流行的軟件包,這是一個實現Apache Kafka協議的C庫。Apache Kafka是一個開源的高性能流處理框架,用于處理實時數據傳輸。librdkafka.redist包有1890萬次下載,其中312000次是2個月前發布的最新版本1.7.0。這個版本的librdkafka.redist使用zlib 1.2.8,但在NuGet或GitHub的項目依賴列表中沒有明確說明。
這個問題在一年多以前就被報告在GitHub上的項目bug追蹤器上,目前被標記為要在1.8.0版本中修復。該項目首席開發者Magnus Edenhill審查了這四個zlib漏洞,并表示其中只有兩個適用于librdkafka,通過Kafka消耗的消息成功利用這些漏洞的風險似乎非常低。Edenhill沒有立即回應評論請求。
其他13個NuGet軟件包依賴于librdkafka.redist,包括一些由一家名為Confluent的數據基礎設施公司開發的軟件包,該公司擁有許多大型企業客戶。
"安全軟件開發是一個復雜的問題,因為它涉及到開發的多個階段的許多參與者,"ReversingLabs的研究人員說。"無論你的公司生產什么類型的軟件,遲早都需要將第三方的依賴關系納入你的解決方案。這將引入管理安全和代碼質量風險的需要。軟件供應鏈攻擊對網絡社區的威脅越來越大。它們是傳統漏洞的DDoS類似物"。
供應鏈風險
NuGet并不是唯一存在這種脆弱依賴問題的軟件包庫,人們可以說,不是由NuGet或其他庫來迫使開發者更關注這些問題。然而,有些平臺比其他平臺更積極主動。GitHub積極掃描其平臺上托管的公共代碼庫,分析它們的依賴關系,如果這些依賴關系中有任何已知的漏洞,就通知其所有者。該公司維護一個公共咨詢數據庫,其中包括npm(JavaScript)、RubyGems(Ruby)、NuGet(.NET)、pip(Python)、Maven(Java)的已知漏洞,并剛剛宣布支持Go模塊。
開源治理公司Sonatype在其《2020年軟件供應鏈報告》中指出,下一代攻擊的數量同比增長了430%,黑客試圖主動向開源軟件項目注入惡意軟件,試圖毒害其依賴鏈上的更多項目和應用程序。黑客利用開源組件中的已知漏洞的傳統攻擊仍然強勁,但利用的時間已經減少,攻擊者在公開披露的幾天內就利用了新發現的漏洞。同時,有一半的公司需要一周以上的時間來了解這些漏洞,并在一周或更長時間后將緩解措施落實到位。
攻擊者顯然對利用軟件供應鏈很感興趣,但成千上萬的具有繼承性漏洞的軟件包仍在公共資源庫中,并作為企業軟件的基礎模塊。