呂蘊藉
針對持續(xù)集成和持續(xù)交付/持續(xù)部署(CI/CD)通道的網(wǎng)絡(luò)攻擊,攻擊者和防御者都越來越明白,構(gòu)建通道是具有重大攻擊面的高權(quán)限目標(biāo)。
但是CI/CD通道的潛在攻擊面是什么呢?這種類型的攻擊實際是什么樣的呢?NCC組織通過不同的安全評估發(fā)現(xiàn)了許多攻擊路徑,這些路徑可能導(dǎo)致大型和小型企業(yè)的CI/CD通道遭到攻擊。
在此,我們展示可能被利用通道上的許多不同類型的攻擊,強調(diào)保護(hù)軟件供應(yīng)鏈的重要性。
從S3桶開始發(fā)起攻擊
S3桶中常見的錯誤配置經(jīng)常會導(dǎo)致整個DevOps環(huán)境的攻擊,最初的攻擊途徑是通過一個Web應(yīng)用程序,該攻擊方案的攻擊流程包括:
Web應(yīng)用-> S3桶上的目錄列表->腳本文件中的硬編碼Git憑據(jù)-> Git訪問->使用相同的硬編碼Git憑據(jù)訪問Jenkins-> Dump憑據(jù)從Jenkins->橫向移動->游戲結(jié)束->事件->內(nèi)部調(diào)查。
NCC組織對一個面向網(wǎng)絡(luò)的Web應(yīng)用程序進(jìn)行了匿名訪問的黑盒Web應(yīng)用程序評估。測試開始時,在一個網(wǎng)站地圖文件夾中發(fā)現(xiàn)了一個網(wǎng)站地圖文件。sitemap文件夾是一個S3桶,啟用了目錄列表。在查看S3存儲桶中的文件時,發(fā)現(xiàn)了一個bash shell腳本。經(jīng)過仔細(xì)檢查,我們發(fā)現(xiàn)了一個帶有證書的硬編碼的git命令,該證書允許NCC集團顧問作為受限用戶訪問Jenkins Master Web登錄界面,該界面只能在內(nèi)部訪問,而不能從互聯(lián)網(wǎng)訪問。點擊幾下鼠標(biāo)并在其中查看之后,他們能夠切換到一個管理員帳戶。憑借管理員權(quán)限,該顧問在腳本控制臺中使用了Groovy單行代碼,并轉(zhuǎn)儲了大約200個不同的憑據(jù),例如AWS訪問令牌、SAST/DAST令牌、EC2 SSH證書、Jenkins用戶和其他Jenkins憑據(jù)。評估結(jié)束時,客戶與顧問密切合作進(jìn)行事件響應(yīng)以進(jìn)行補救。
NCC為客戶提供了一份詳細(xì)的報告,其中包含修復(fù)和強化步驟,其中一些推薦步驟如下:
1.刪除S3的目錄列表;
2.刪除shell腳本文件和硬編碼憑據(jù);
3.刪除允許任何擁有GitHub訪問權(quán)限的人都可以訪問Jenkins的連接;
4.安裝和審查審計跟蹤和作業(yè)配置歷史插件;
5.在現(xiàn)場測試的情況下,不應(yīng)該通過互聯(lián)網(wǎng)訪問Jenkins;
6.更改和降低Jenkins帳戶擁有的權(quán)限;
7.為管理員帳戶部署和使用MFA。
強化環(huán)境中的權(quán)限升級
在不同評估中發(fā)現(xiàn)的另一條權(quán)限升級路徑的步驟如下:
使用SSO憑據(jù)登錄->測試分離、鎖定和記錄的角色->一個具有構(gòu)建/重播代碼執(zhí)行的角色->憑據(jù)轉(zhuǎn)儲。
評估的目的是審查一個新實現(xiàn)的強化Jenkins環(huán)境,該環(huán)境包含使用最小權(quán)限原則創(chuàng)建的記錄用戶角色。Jenkins在非root用戶下運行,最新版本的核心和插件,具有SSL認(rèn)證和SSO,使用MFA進(jìn)行登錄。NCC組織顧問每天訪問一個具有特定角色的用戶,并測試是否存在任何權(quán)限升級路徑。
構(gòu)建器角色也具有構(gòu)建/重播權(quán)限,這允許使用修改過的腳本或額外的Groovy代碼重播Pipeline構(gòu)建,而不僅是建作業(yè)的構(gòu)建權(quán)限。這允許NCC組織顧問運行Groovy代碼并轉(zhuǎn)儲Jenkins用戶的憑據(jù)和其他秘密。
插件中令人困惑的語言表達(dá)
最后一個途徑是在Jenkins插件中發(fā)現(xiàn)的一個令人困惑的選項,它導(dǎo)致了完全開放的訪問。
GitHub授權(quán)->具有讀取權(quán)限的經(jīng)過身份驗證的Git用戶->使用Gmail帳戶的Jenkins訪問權(quán)限。
GitHub OAuth插件部署在Jenkins中,提供身份驗證和授權(quán)。勾選了“向所有經(jīng)過身份驗證的用戶授予讀取權(quán)限”和“使用GitHub存儲庫權(quán)限”選項,允許任何擁有GitHub帳戶的人(甚至是外部用戶)訪問Jenkins Web登錄UI。NCC能夠注冊并使用他們自己的托管電子郵件帳戶來訪問項目。
NCC集團已經(jīng)做了很多工作,研究了另一個眾所周知的被使用的工具GitLab。因此,NCC組織顧問發(fā)現(xiàn)了一些有趣的攻擊路徑。
利用受保護(hù)的分支
在一項特定的工作中,GitLab runner的設(shè)置存在多個主要漏洞。第一個主要漏洞是,runner使用了權(quán)限容器,意味著它們被配置為使用“-privileged”標(biāo)志,這將允許它們啟動其他可以輕易逃逸到主機的特權(quán)容器。這是一個非常簡單的攻擊媒介,可以讓你到達(dá)主機,但有趣的是,這些GitLab runner也共享runner,而不是孤立的。一位只應(yīng)該將代碼推送到某個存儲庫的開發(fā)人員也可以訪問機密和高權(quán)限存儲庫。此外,這些共享運行程序使用的是存儲高度敏感秘密(如身份驗證令牌和密碼)的普通環(huán)境變量。對存儲庫具有有限的推送訪問權(quán)限的用戶可以獲得高度權(quán)限的機密。
受保護(hù)的分支是可以由GitLab中具有維護(hù)者角色的人維護(hù)的分支,只有這些人具有推送這些源代碼存儲庫或分支的權(quán)限,并且有一個與之關(guān)聯(lián)的更改請求(CR)鏈。這些受保護(hù)的分支可以與受保護(hù)的運行程序相關(guān)聯(lián)??梢詫⑵滏i定,因此開發(fā)人員必須獲得CR批準(zhǔn)才能推送代碼,但在這種情況下,沒有實施和執(zhí)行CR和受保護(hù)的分支。任何人都可以推送到未受保護(hù)的分支,然后鏈接以前的漏洞利用,這4~5個漏洞的鏈接提供了所有訪問權(quán)限。
也有很多不同的路徑。即使使用了“-privileged”標(biāo)志,也有另一條路徑可以訪問特權(quán)容器。操作人員需要能夠運行docker命令。主機的docker守護(hù)進(jìn)程與GitLab共享Runner共享,這導(dǎo)致了對主機的訪問和在容器之間的切換。
顧問要求客戶了解并幫助糾正這些問題,但很想了解導(dǎo)致作出這些選擇的根本原因。他們?yōu)槭裁醋龀鲞@些配置選擇,他們考慮了哪些權(quán)衡?除了這些選擇,還有什么更安全的選擇呢?他們知道這些選項嗎?如果知道,為什么不選擇他們?
公司想要權(quán)限容器的原因是對被推送的代碼進(jìn)行靜態(tài)分析,顧問解釋說,他們應(yīng)該使用隔離的runner,而使用共享的runner,并且應(yīng)該有進(jìn)一步的訪問控制限制。要注意的是,可以運行權(quán)限容器,但仍然可以在一定程度上限制暴露的敏感信息的數(shù)量。
GitLab執(zhí)行作業(yè)的許多CI/CD安全機制依賴于這樣一個前提,即受保護(hù)的分支只包含受信任的構(gòu)建作業(yè)和由項目維護(hù)者管理的內(nèi)容。項目維護(hù)者權(quán)限級別或更高級別的用戶可以委托其他用戶管理和推送到特定的受保護(hù)分支。這些有權(quán)限的用戶是表示項目中什么是可信的,什么是不可信的網(wǎng)關(guān)。進(jìn)行這種區(qū)分對于緩解對不可信構(gòu)建作業(yè)的權(quán)限暴露非常重要。
使用權(quán)限容器的GitLab runner
在另一個操作中,GitLab runner被配置為使用Docker的“—privileged”標(biāo)志執(zhí)行CI/CD作業(yè)。這個標(biāo)志將否定Docker提供的任何安全隔離,以保護(hù)主機免受潛在的不安全容器的攻擊。通過禁用這些安全功能,容器進(jìn)程可以通過各種功能將其權(quán)限升級到主機上的root權(quán)限。一些工具被打包成Docker映像,為了支持這一點,客戶端在Docker(DIND)中使用一個權(quán)限容器中的Docker來執(zhí)行嵌套的容器。
如果有權(quán)限的CI/CD作業(yè)是必要的,那么相應(yīng)的runner應(yīng)該配置為只在已知合法的受保護(hù)的項目分支上執(zhí)行。這將防止任意攻擊人員提交可能導(dǎo)致主機被攻擊的未經(jīng)審查的腳本。維護(hù)者角色管理項目受保護(hù)分支的能力意味著他們控制由相關(guān)受保護(hù)的Runner提供的任何權(quán)限。
高權(quán)限共享Runner可能會請求與敏感環(huán)境變量和權(quán)限Kubernetes環(huán)境相關(guān)的工作。
權(quán)限運行程序不應(yīng)配置為共享運行程序或廣泛作用域組,相反,它們應(yīng)該根據(jù)特定項目或組的需要進(jìn)行配置,這些項目或組被認(rèn)為在維護(hù)者級別或更高級別的用戶之間具有相同的權(quán)限級別。
Runner將秘密暴露給不可信的CI/CD作業(yè)
運行程序調(diào)用API終端,這些終端使用各種令牌和密碼進(jìn)行身份驗證。因為這些是共享Runner,任何有權(quán)限向Gitlab提交源代碼的用戶都可以輕松地訪問身份驗證令牌和密碼。Runner被配置為通過環(huán)境變量公開秘密。秘密管理,特別是CI/CD通道的秘密管理是一個難以解決的問題。
要緩解這些類型的風(fēng)險,請確保由runner在所有構(gòu)建作業(yè)中配置的環(huán)境變量不包含任何權(quán)限憑據(jù)??梢允褂眠m當(dāng)作用域的GitLab變量作為替換。環(huán)境變量應(yīng)該只包含信息配置值,應(yīng)該認(rèn)為相關(guān)項目和組中的任何被利用人員都可以訪問這些配置值。如果Runner必須通過環(huán)境變量或掛載的卷為其作業(yè)提供憑據(jù),那么Runner應(yīng)該限制它們所暴露的工作負(fù)載。為此,此類Runner應(yīng)僅與最具體的可能項目/組相關(guān)聯(lián)。此外,它們應(yīng)該被標(biāo)記為“受保護(hù)的”,以便它們只能處理受保護(hù)的分支上的作業(yè)。
主機Docker守護(hù)進(jìn)程暴露給共享的GitLab Runner
在一次操作中,Gitlab共享Runner在運行時將主機的Docker套接字掛載到CI/CD作業(yè)容器中。雖然這允許合法的開發(fā)人員為了構(gòu)建目的在主機上運行任意Docker命令,但它也允許構(gòu)建作業(yè)在主機上部署權(quán)限容器,以逃避它們的約束。這也為攻擊者提供了一個窗口,通過這個窗口他們可以攻擊在主機上運行的其他構(gòu)建作業(yè)。本質(zhì)上,這否定了Docker所提供的所有隔離,阻止被包含的進(jìn)程訪問其他容器和主機。在這種情況下,建議采取以下緩解措施:
1.不允許開發(fā)人員直接與不受其控制的主機上的Docker守護(hù)進(jìn)程交互??紤]使用支持無根Docker構(gòu)建的工具(例如kaniko)運行Docker構(gòu)建作業(yè)。
2.開發(fā)一個進(jìn)程,在源代碼存儲庫上運行一組靜態(tài)Docker命令來構(gòu)建它們。此過程不應(yīng)在CI/CD作業(yè)本身內(nèi)執(zhí)行,因為作業(yè)腳本是用戶定義的,并且可以覆蓋命令。
3.如果這必須通過CI/CD作業(yè)來實現(xiàn),那么在這些Runner上執(zhí)行的構(gòu)建作業(yè)應(yīng)該被視為特權(quán),因此應(yīng)該限制Docker Runner接受提交了保護(hù)和已知的安全存儲庫以確保任何用戶定義的CI / CD工作已經(jīng)通過了正式的審批程序。
Kubernetes
運行特定功能的pod有時會使用不同的pod身份驗證機制,這些機制可以連接到各種服務(wù),AWS憑據(jù)就是一個例子。很多時候,人們使用插件,并不限制插件周圍的API路徑。例如,Kube2IAM是一個經(jīng)??吹降牟寮?,如果你沒有從pod中正確地配置它,你可以獲得權(quán)限容器,它可以導(dǎo)致具有特權(quán)API憑據(jù),讓你看到底層主機正在做什么。
Kube2IAM
Kube2IAM使用pod注釋。它攔截來自容器pod對AWS API (169254)的調(diào)用。NCC組織的一位顧問發(fā)現(xiàn)了一個有趣的情況,每個開發(fā)人員都可以對pod進(jìn)行注釋。在Kube2IAM使用的AWS角色中,有一個使用“sts assume-role *”行配置的設(shè)置。這使得任何能夠創(chuàng)建/注釋pod的被利用人員都繼承了AWS的管理員角色。這意味著任何可以創(chuàng)建任意pod并指定注釋的人都可以獲得一家銀行AWS主工具帳戶的管理權(quán)限。此帳戶配置了VPC對等互連,可以查看任何pod和非pod環(huán)境。你可以使用該訪問權(quán)限到達(dá)任何地方。這是一個構(gòu)建pod的通道,攻擊者所要做的就是在最后輸出一些東西的注釋中添加一個注釋。
NCC組織的一位顧問還進(jìn)行了另一項類似的工作,在這種情況下,他們無法對pod進(jìn)行注釋。相反,在Kube2IAM中有標(biāo)記“白名單路由正則表達(dá)式”,你可以提及AWS API路徑,可以指定你想去或不去的路徑,DevOps管理員已經(jīng)將其配置為一個白色字符,允許某人訪問權(quán)限路徑,從而導(dǎo)致底層節(jié)點憑據(jù)。
利用筆記本電腦發(fā)起攻擊
NCC組織顧問進(jìn)行了基于場景的評估———利用開發(fā)人員的筆記本電腦。
顧問所能做的就是將代碼提交到使用Maven項目的單個Java庫中。他們將一個前置需求文件設(shè)置為一個任意文件,該文件將提供來自構(gòu)建環(huán)境的shell。他們將其更改為反向Meterpreter shell有效負(fù)載。他們發(fā)現(xiàn)pod有一個SSH密鑰位于磁盤上,該密鑰進(jìn)入Jenkins主節(jié)點,然后從Jenkins中轉(zhuǎn)儲了所有變量。然后他們發(fā)現(xiàn)這是一個真正的部署通道,它擁有寫入權(quán)限和集群管理到Kubernetes工作負(fù)載中。因此,他們現(xiàn)在可以訪問完整的生產(chǎn)環(huán)境。
在另一項操作中,NCC組織顧問成功攻擊了一個用戶帳戶,并訪問了經(jīng)過驗證的通往被利用團隊的通道。在通道中運行自定義代碼是不可能的,但是他們可以告訴通道構(gòu)建一個不同的分支,即使它不存在。通道崩潰并轉(zhuǎn)儲環(huán)境變量。其中一個環(huán)境變量是Windows域管理員帳戶。在該攻擊場景中,他們能夠?qū)A(chǔ)設(shè)施進(jìn)行端口掃描,最終形成一個構(gòu)建通道。他們發(fā)現(xiàn)了許多功能未知的應(yīng)用程序,其中一個應(yīng)用程序容易受到服務(wù)器端請求偽造(SSRF)的攻擊,它們運行在AWS EC2實例上。AWS節(jié)點能夠編輯配置映射,允許AWS用戶帳戶和集群內(nèi)角色之間的映射。結(jié)果,這并沒有檢查集群和帳戶是否在同一個用戶帳戶中。因此,顧問可以指定另一個AWS帳戶來控制集群,并在Elastic Kubernetes服務(wù)集群(EKS0)上擁有管理權(quán)限。