近期軟體供應鏈攻擊頻傳,最近發生在Npm上的攻擊,更是由套件作者本人發動,但由於現代軟體工程建立在協作之上,並且重度仰賴開源軟體,這使得企業軟體不得不面對,來自相依項目所進行的供應鏈攻擊。Go官方在自家部落格,詳細說明Go開發工具和流程設計,足以降低各階段遭到攻擊的風險。

Go防禦供應鏈攻擊第一招便是鎖定建置,使得外部的更改,都無法自動影響Go的建置,官方提到,與大多數的套件檔案管理不同,Go模組沒有獨立的限制列表,或是可以鎖定特定版本的釘選檔案,參與Go建置的每個相依項目的版本,完全由主模組的go.mod檔案控制。

從Go 1.16開始,系統預設在go.mod不完整的情況下,建置命令包括go build、go test、go install和go run等命令將會執行失敗,唯一會改變go.mod與建置的命令,是go get和go mod tidy,但這兩個命令並不會自動執行或是在CI中執行,因此要對相依關係樹做出更改,必須是刻意為之,並且有機會經過程式碼審查。

而且利用go get命令添加相依項目時,會使用go.mod中指定的版本而非最新版本。由於此機制,當模組被入侵並發布新的惡意版本時,在專案明確更新相依項目之前,既有程式碼都不會受到影響,而這也提供生態系審查更改和偵測事件的機會。

另一個確保第三方無法影響建置的關鍵屬性,是模組版本內容無法改變,因為當破壞相依項目的攻擊者,可重新上傳現有版本,便能夠進一步破壞相依於該模組的專案。而go.sum檔案包含了相依項目的加密雜湊列表,因此能夠驗證模組的真偽,僅有go get和go mod tidy能夠修改該檔案,而任何go.sum的任何變更都會是刻意進行的相依項目變更。

另外,Go把版本控制系統當作唯一的事實來源,官方解釋,大多數的專案都是利用版本控制系統進行開發,並且上傳到套件儲存庫,而這代表其中有兩個環節可能受到攻擊,其一是版本控制系統主機,另一個則是套件儲存庫,而後者因為較少被關注,因此更容易被上傳包含惡意程式碼的套件版本到儲存庫。

但是在Go中,不存在套件儲存庫帳戶,套件的匯入路徑擁有go.mod擷取套件必要的資訊,Go會從版本控制系統直接取得套件。雖然Go模組有鏡像站點,但僅是一個代理,模組作者不需要註冊帳戶,也不需要將版本上傳到代理,代理使用與Go工具相同的邏輯快取套件版本。

Go第四招防禦供應鏈攻擊,是將擷取和建置的程式碼視為不受信任和存在惡意的,因此在建置程式碼後不自動執行該程式,這是Go工具鏈中明確的安全設計原則,和大多數生態系在擷取套件時執行程式碼不同。

官方提到,安裝後的Hooks過去曾被用作感染開發者機器的手段,而這是透過模組作者散布蠕蟲最方便的方法,不過,因為通常開發者在擷取程式碼後,便會在之後執行,因此無論是作為開發人員機器上的測試,還是生產二進位檔案的一部分,缺少安裝後Hooks,也只會影響攻擊者的速度,但卻是一種有意義的風險緩解措施。

第五招供應鏈攻擊防禦招式,是拒絕大型相依樹的文化,Go傾向複製而不是添加新的相依項目,官方提到,這可能是Go生態系中最重要,但是技術性最低的軟體供應鏈風險緩解措施。簡單來說,在開發者使用一個函式庫時,不會發現需要同時仰賴其他數十個模組,而這能大幅降低供應鏈風險。

熱門新聞

Advertisement