CODING 代碼資產安全系列之 —— 構建全鏈路安全能力,守護代碼資產安全

本文作者:王振威 - CODING 研發總監
CODING 創始團隊成員之一,多年系統軟件開發經驗,擅長 Linux,Golang,Java,Ruby,Docker 等技術領域。近兩年來一直在 CODING 從事系統架構和運維工作。

不同類型的企業資產有不同的管理辦法,但守護資產的安全性無一例外都是重中之重,但對如何保障代碼資產安全並沒有形成統一認知。本文將就“代碼資產的安全性”這一話題展開全面的闡述,嘗試從代碼管理的生命週期進行全鏈路分析,讀者可以據此來審視自己企業的代碼資產安全。

代碼資產安全是什麼

代碼資產安全不等於信息安全

代碼資產安全不等於信息安全,這是很容易理解的。整個企業的信息系統組成不僅僅是代碼資產,甚至可以說大多數情況下不涉及代碼資產。企業的信息系統往往由基礎計算設施、網絡平臺、軟件、數據庫等方面組成。信息安全重點是關注上述信息設施在投產之後運行過程中的安全問題。而大多數軟件運行的程序包是經由源代碼編譯的結果,跟源代碼本身是分割開來的。信息安全關注的方面更爲全面,代碼資產安全只是其中的一部分,而且往往不是最爲關注的一部分。

代碼資產安全不等於代碼安全

代碼資產安全不等於代碼安全,這不太容易理解。代碼安全往往指代代碼本身的安全性,如代碼中是否有遠程過程執行漏洞,注入漏洞等等。而代碼資產安全是一個管理概念,強調管理過程的安全,而非代碼本身安全,例如某研究機構需要研究某種計算機病毒,他們需要在源碼庫中存放對應病毒的源碼。這病毒的源碼就是這個機構的重要資產。

代碼管理系統不審視源碼中的漏洞或者惡意行爲,而是必須忠實地確保存儲的代碼的原始文件

代碼資產管理是圍繞代碼倉庫的全生命週期管理

代碼資產管理的核心是代碼倉庫。倉庫裏存放着企業的全部代碼,配置文件以及全部歷史版本。守護代碼資產安全的核心就是圍繞代碼倉庫的三個關鍵環節構建起全鏈路的安全能力,這三個環節分別是檢入,存儲和檢出

檢入安全

檢入可以理解爲開發者在開發環境上編輯好代碼,並且把代碼傳送到代碼倉庫的過程。這個環節關注兩個方面,分別是機密性完整性

機密性

機密性是指開發者把開發環境中的代碼檢入代碼倉庫的過程不被第三方竊取,一般通過傳輸過程加密來實現。Git 代碼倉庫最常用的是 HTTPS 和 SSH 傳輸協議。

HTTPS 協議是通過 HTTP 協議加上傳輸層安全協議(TLS)實現的。HTTP 協議是明文傳輸協議,這意味着如果沒有 TLS,網絡節點中的路由設備都可以輕鬆竊取代碼。TLS 可以在 TCP 協議之上建立雙向加密能力,配合 HTTP 協議上就是 HTTPS。HTTPS 客戶端和服務端先通過非對稱加密協商加密算法和密鑰,再使用協商的算法和密鑰來進行對稱加密傳輸。本文不涉及具體算法的安全性介紹,不過隨着密碼學的發展,算法在與時俱進,我們可以認爲加密算法本身是安全的。

然而這一過程並不完備,攻擊者可以製作中間服務器,使得客戶端在發起連接的時候誤連接了中間服務器,從而跟這個中間服務器進行加密通信。這將導致即便是加密傳輸,但最終還是會被惡意服務器竊取,這就形成了中間人攻擊

行業推出了 CA(證書授權機構)機制應對此問題,即服務器在提供加密傳輸服務前,要把自己的公鑰和服務的域名綁定,並且在全球公信的 CA 處登記。這樣一來,HTTPS 客戶端在嘗試建立加密鏈接的時候,會要求服務器出示 CA 簽發的證書,客戶端可以使用預安裝在操作系統或者瀏覽器內的 CA 公鑰進行驗證,確認服務器對域名的所有權,這樣一來就可以確保不會有中間人攻擊。有行業公信力 CA,也有企業內部 CA,而後者需要在客戶端安裝企業內部 CA 的證書文件。

知名安全機構 Qualys 可以在線對 HTTPS 服務器進行 SSL/TLS 多方面的報告評估,如下圖爲兩家國內雲計算公司推出的代碼託管服務器的評估:

HTTPS 雖然解決了傳輸安全,但在認證用戶身份這裏,Git 代碼倉庫還是依賴 Basic Auth 機制來實現。Git 代碼倉庫會要求 HTTPS 客戶端提供賬號密碼,並附在請求體中一併傳輸給服務器,由服務器來確認操作者身份。在傳輸過程中,賬號和密碼是被 TLS 一併加密傳輸的,我們不必擔心傳輸過程的密碼泄露問題。但開發者通常爲了不必每次操作都輸入賬號密碼,會讓電腦記住密碼,如果不妥善處理,可能會導致泄露。這裏重點是一定不能把賬號密碼拼接在遠程倉庫訪問地址裏面,正確的做法是使用 Git 在各種操作系統下的 憑據管理器,如 macOS 是使用鑰匙串管理,Windows 是使用 Git Credential Manager for Windows 來進行管理。

SSH 是一種常用於遠程管理 Linux/Unix 服務器的安全加密協議,其功能非常多樣。以 Git 爲基礎的代碼託管也常使用這個協議進行加密代碼傳輸。使用者提前把自己的公鑰文件配置在服務器上後,可以在後續的傳輸過程中確認身份。

SSH 使用非對稱加密(用戶的公鑰)確認身份,用對稱加密傳輸數據。跟 HTTPS 不同的是,SSH 協議無法指定域名,所以無法引入 CA 機制來防止中間人攻擊。

但 SSH 客戶端在與未知服務器進行連接時,會提示服務器的公鑰指紋信息,使用者應當對比服務供應商官方提供的公鑰公告和命令行提示信息來確認服務器身份,確保不被中間人攻擊。

如圖展示騰訊雲 CODING SSH 服務器的公鑰指紋公示:

如圖所示,SSH 客戶端嘗試連接服務器時給出的服務器公鑰指紋確認:

在用戶確認身份(輸入 yes 並按下回車)後,SSH 客戶端會把服務器的公鑰信息記錄在 ~/.ssh/known_hosts 中,下次即可直接連接,不再詢問。

要點小結

  • 代碼的傳輸要使用雙向加密協議,HTTPS 和 SSH 都可以
  • HTTPS 協議需要關注服務器的證書籤發方(CA)的權威性
  • HTTPS 協議需要關注客戶端是否安裝了不受信任的 CA 文件(防止 CA 欺詐)
  • 使用 Git 憑據管理器保管 Git HTTPS 協議的賬號密碼
  • SSH 協議在使用的時候需要仔細比對服務器提供的公鑰指紋跟服務提供商公告的公鑰指紋是否完全一致,防止中間人攻擊
  • 客戶端需要注意防止攻擊者惡意篡改 ~/.ssh/known_hosts 文件內容或者 SSH 的客戶端配置(可以通過忽略服務器公鑰信任機制)
  • 妥善保管 SSH 私鑰文件(往往存放於 ~/.ssh/id_rsa),如 Linux 下確保此文件的權限是 400 等,防止他們讀取

完整性

代碼檢入的完整性包含兩個方面:

  1. 開發者一次提交的代碼變動是否完整(內容不被篡改)
  2. 某次提交是否確爲某開發者做出的變動(不被冒名頂替)

以 Git 爲例子,這個代碼版本控制軟件已經從內生機制上確保了內容不被篡改。Git 採用一種類 Merkel 哈希樹的機制來實現分層校驗。

哈希是一種把任意數據映射成等長數據的算法,且不可逆。哈希算法有的特點是原始數據發生一點變化,映射的結果會產生較大變化,而且這一變化毫無規律。映射後的等長的數據被稱爲指紋。

哈希算法非常適合用來快速比較兩段數據是否完全一致(指紋一致幾乎可以推斷原文一致)。在我們上文中提到的對比 SSH 服務器出示的公鑰指紋,和服務提供商公告的指紋就是這種原理的應用。

Merkel 哈希樹:

Git 對倉庫中的每一個文件內容和其基本信息整合進行哈希。會將一個目錄樹下的所有文件路徑和文件哈希值組合再哈希形成目錄樹的哈希。會把目錄樹和提交信息組合再哈希,此哈希結果就是 Git 的版本號。這意味着每次提交都產生一個完全不同的版本號,版本號即哈希。在給定一個版本號,我們可以認爲這個版本背後對應的全部文件內容,歷史記錄,提交信息,目錄結構都是完全一致的。對於確定的版本號就沒有篡改的可能性

哈希算法小概率會產生衝突(同一個指紋對應多個不同原始數據的情況),這時可能導致一致性校驗失效。所以哈希算法也在與時俱進,如當下 MD5 算法已經幾乎過時,Git 當前正在使用 SHA1 算法,未來可能會升級到更爲安全的 SHA256 算法。

如圖展示 Git 中的某個目錄樹的內容信息:

即便開發者自己提交的版本經過 Git 的層層哈希,可以確保內容不被惡意篡改,但仍然有被冒名頂替的危險

因爲 Git 在提交過程不需要驗證用戶身份,而且提交可以被不同的人在各種傳輸過程中傳輸和展示。設想攻擊者冒充公司員工製造一個提交,卻被公司其他員工認爲是公司內部人士會有多可怕。目前基於 Git,業界的普遍做法是引入 GPG 簽名機制

GPG 是基於非對稱加密算法的一個應用,其原理是使用私鑰處理一段信息,得到一段新的信息,這段新的信息只能由私鑰生成,而且可以使用對應的公鑰來識別這段新的信息的生成來源,這段新的信息就被稱爲數字簽名。

簡單來說,信息發佈者使用自己的私鑰(私人印章)對要發佈的信息(待簽名文件)進行簽名,並且把原始文件和數字簽名一併發送給使用方。使用方持有發佈方的公鑰,對收到的數字簽名和原始文件進行校驗就可以確認確實是發佈方發出的,未被冒名頂替。這類似給要發佈的信息蓋了個章。

如圖展示 Git 中某個提交被開發者添加 GPG 簽名的效果:

要點小結

  • Git 本身的哈希機制可確保內容不被篡改
  • 使用 GPG 爲提交簽名可防止冒名頂替
  • 服務器端要校驗 Git 提交郵箱聲明和 GPG 簽名

存儲安全

存儲安全是指當代碼被檢入到代碼倉庫後,如何保證數據的機密性,完整性和可用性。拋開基礎設施的安全性不談,對於代碼存儲來說,數據往往由數據庫數據和代碼庫文件組成,這裏重點討論代碼文件存儲安全問題。

機密性

代碼倉庫中的代碼大多直接存放於操作系統的磁盤中,在服務器軟件進行讀寫操作的時候,不涉及網絡傳輸的機密性風險,但直接寫入磁盤上的文件在未做控制的情況下,往往可以被操作系統上的很多不相關進程隨意讀寫,這些非預期的代碼讀寫會造成額外的風險。

一種做法是去控制每一個文件的讀寫權限,如統一設置爲 600,另一種做法是乾脆只允許服務器上運行一個業務進程,實現操作系統級別隔離。

容器技術提供了一種良好的隔離進程方案:如在 Kubernetes 體系下,代碼倉庫存儲在 PV 上,並只被掛載進代碼倉庫的應用容器內讀寫,而且基於容器的調度和彈性特性可以較好的支持高可用並避免資源浪費。

完整性和可用性

我們知道 Git 本身會通過哈希校驗機制來確保倉庫的完整性,但前提是倉庫文件是完備的。如果倉庫的文件丟失或者損壞,Git 的哈希校驗也將無法工作。數據的完整性有很多種解決方案,最常見的冷備,半實時備份,實時備份,磁盤快照等方案都是爲了確保文件在丟失或者損壞的時候可以找回,來確保倉庫的完整性的。不過總的來說,備份往往是事後的恢復手段,無法實現即時的自愈,最終依據備份機制來進行數據修復往往會影響可用性。

雖然業界沒有針對代碼倉庫的通用高可用方案,但數據庫主從策略和 RAID 機制是兩個可以參考的做法,這裏來做下簡要介紹。

數據庫主從策略,一種做法是數據寫入主庫,從庫自動增量同步數據。當主庫發生故障時,從庫自動替代。代碼存儲類似,可以把存儲節點分爲主節點和從節點。

RAID 機制是一種磁盤分片存儲的冗餘機制,有多種做法,如 RAID5,分片存儲,並存儲一份校驗信息,當任意一塊磁盤壞掉,可以通過校驗信息來複原數據。

騰訊雲 CODING DevOps 在這方面進行了深入研究,並結合了主從和 RAID 的思路,實現了針對代碼倉庫的高可用策略,可妥善保障倉庫的完整性。

如圖所示,對於 D 倉庫來說,他的主倉庫 D(m) 存放於第二個節點,他的從倉庫 D(s) 存放於第一個節點(實質上還可以設定更多從倉庫,這裏爲了圖示方便,只顯示了一個)。這樣的設計讓各個節點都可以不閒置計算資源,而且任意一個節點出現損壞都可以快速恢復。

檢出安全

代碼檢出後才能使用,而檢出也涉及傳輸機密性問題,這點與檢入部分沒有區別。而對於 Git 倉庫來說,檢出環節的倉庫完整性會由 Git 的哈希校驗機制保證,也不會有太大問題。檢出環節的安全問題往往是因爲不合適的權限策略和密鑰管理導致代碼泄露

企業內部代碼通常有如下四個場景:

  1. 檢出開發
  2. 閱讀評審
  3. 自動執行(CI,自動化測試等)
  4. 管理審計

檢出開發權限

需要區分開發者能讀寫的權限範圍,保護好關鍵資源和密鑰,按如下原則:

  • 按照業務、組件等進行分門別類的存放,倉庫隔離
  • 根據所處的部門和組織關係配置倉庫的權限
  • 爲分支設定讀寫權限,只允許有權限的成員寫入
  • 使用文件鎖定方式保護敏感文件不被誤修改
  • 統一傳輸協議,如只允許 HTTPS 或者 SSH
  • 爲個人密碼,令牌,公鑰等設定有限期
  • 審計密碼,令牌,公鑰等的使用記錄
  • 爲目錄設定讀寫權限,只允許指定開發者讀取或者寫入某些目錄
  • 禁止強制推送策略,防止代碼被回退

如圖所示,設置倉庫內的目錄權限:

閱讀評審權限

訴求是看源碼和輔助信息,並做出自己的評審結果,不涉及寫入代碼,按如下原則:

  • 區分讀寫和只讀成員羣體,禁用後者的寫入權限
  • 區分深入評審和輕量級評審,禁用後者的代碼檢出權限,只允許其 Web 頁面查看源碼
  • 使用 CODEOWNERS 機制自動指定評審成員

如圖所示,設置倉庫的 CODEOWNERS:

自動執行權限

自動檢出,檢出行爲背後不對應一個人,不涉及代碼寫回,按如下原則:

  • 禁止成員把自己的密碼,令牌,密鑰用於自動執行
  • 使用項目/倉庫令牌,部署公鑰機制確保令牌和密鑰只對指定倉庫有權限
  • 爲不同場景設置專用的令牌,不得混用,也不得用於其他用途
  • 爲令牌,公鑰等設置有效期
  • 爲令牌,公鑰等設置禁止寫入權限
  • 審計令牌,公鑰等的使用記錄

如圖所示,設置令牌的權限和有效期:

管理審計權限

這種場景是非技術人員希望瞭解倉庫統計信息,活躍情況,瞭解研發過程進度等,按如下原則:

  • 給成員開放所管轄的倉庫列表和倉庫詳情的 Web 頁訪問權限
  • 禁止成員使用 HTTPS/SSH 協議把源碼檢出到本地
  • 禁止成員在網頁端下載源碼包

如圖所示,設置禁止倉庫寫入等權限

總結

代碼資產管理是個體系化的工程,這個過程中的安全性不是某個單點可以完全保障的,需要從檢入,存儲,檢出三個環節對全鏈條進行風險分析。很多企業在這些方面很重視,但聚焦錯了方向,可能付出了很大努力,但實質上依然冒着代碼資產的丟失和泄露的巨大風險。希望此文可以幫助企業正視代碼資產安全,爲代碼資產管理者提供一個審視安全的基本框架。

讓 CODING 爲您的代碼資產保駕護航

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章