《專家觀察 | 張謙:“Docker逃逸與防護策略”》要點:
本文介紹了專家觀察 | 張謙:“Docker逃逸與防護策略”,希望對您有用。如果有疑問,可以聯系我們。
由工業和信息化部指導,中國信息通信研究院主辦,業界知名組織云計算開源產業聯盟(OSCAR)承辦的2017全球云計算開源大會于4月19日-20日在北京國家會議中心順利召開.本文為本屆大會嘉賓分享的大會演講速記內容,敬請瀏覽.
嘉賓介紹:張謙
公司職務:奇虎360科技有限公司安全研究員
大會演講速記
各位來賓,大家下午好!我是來自奇虎360運營安全研究部的安全研究員張謙.
我想先在這兒介紹一下我們團隊,大家關注虛擬化產品的安全研究上面可能會對我們團隊稍微熟悉一點.我們團隊成立于2015年年底,主要的研究方向是虛擬化產品的安全漏洞,我們團隊先后在虛擬化產品,比如說Docker、VMware,從2015年底到現在一共發現了幾十枚安全漏洞,都通報給了CVD,都有相應的編碼.
說起我們團隊在今年3月份全球頂級的黑客大會上,加了一個逃逸的比賽項目,因為這個比賽是持續三天,最后一天比賽上我們團隊貢獻了一枚VMware的Docker逃逸,我們最后一天搞了一個什么項目?可以通過一個網頁,攻擊者可以通過網頁完成本地拿我們的VMwareDocker逃避直接到宿主機.
安全研究的思路以攻促防,以我們安全研究的攻擊思路和這些年的技術積累,幫助360在旗下的安全產品上提供一些技術上其他團隊沒有辦法預約的技術壁壘,把這些相應的攻防經驗融入到360旗下的安全產品里面.
剛才前幾位嘉賓都講解了他們公司也好或者他們公司產品的組織架構,我本身是一個技術出身的,所以我今天帶來的干貨是一些跟技術關聯比較大的東西.因為我們團隊在2016年上半年完成了Docker逃逸,從Docker容器逃逸到整個Docker的物理機里邊.今天我就給大家講講Docker逃逸與防護策略.
Docker可能在座各位應該在云安全行業里面也是不陌生的這么一個東西,也是前一陣炒得比較火,Docker本身是開源項目,是用Go語言寫的開源項目,是一個非常輕量化的解決方案,實際上它的基礎就是Linux(LXC),讓用戶感覺處在真實一個虛擬機里面一樣.
這是一個對比圖,一個傳統的虛擬機還有Docker容器帶來的虛擬化,可以看上面,傳統虛擬機需要虛擬出硬件設備,也就是需要虛擬處一個操作系統出來.
Docker實際上利用Docker容器和真正的物理機,實際上用的都是一個操作系統的內核,也就是說它在資源消耗上少了一個HostOS本身需要消耗很多資源,相比傳統的虛擬機來說這是它的優點.
這是從數量級上面的對比,Docker在啟動的時候實際上就跟Linux的進程一樣,啟動的是時候秒級,虛擬機至少需要幾十秒時間,這是它的硬盤的消耗.
假設我們現在有這么一種應用場景,比方說一臺16核32G內存的主機上面需要跑幾百個應用,每個應用上面是一個網站,虛擬機需要至少做到兩點,一種是資源隔離,這個虛擬機的操作不能影響到其他虛擬機,首先假如說我們在這樣一臺基礎上開500個虛擬機,本身虛擬化所帶來的消耗是非常嚴重的,但是如果用Docker,Docker本身就相當于是一個Linux上的進程,開500個進程在這樣一臺配置的主機上絕對沒有什么問題的.
接下來給大家講講Docker的一些核心技術,實際上Docker本身因為本身沒有做完全的虛擬化,很多東西用的都是里面支持的一些內核特性.比如說第一個是一個命名空間,Docker本身提供了6個命名空間,這個命名空間有沒有用?Docker容器在不同的命名空間里邊是不能影響其他容器的.
Docker一共提供了6種NameSpace,就是主機名用戶名@之后有一個主機名,Docker就可以就把這個主機隔離開,有一個信號量,還有進程編號,在初始化之后有一個引進進程,在Docker容器里面編號啟動之后全都是從E開始的.還有網絡設備,也是全隔離的.還有文件系統,你在Docker容器里做文件操作是不能影響其他容器的.User和Mount是隔離用戶組,每個用戶在容器里面在里面的權限是不一樣的.
這是系統調用參數,從名字上來看,可以看clone,有UTS對應,IPC對應,PID也是對應,唯一不同的是Mount,實際上Mount的歷史實際上是第一個支持的NameSpace,當然了內核維護者沒有想到之后還會出來12345,所以它在實現Mount的時候就直接就是NameSpace.
這里有一些技術,就是掃代碼,剛才前幾位都講產品,我給大家換換腦子.在NameSpace里面有一個描述符,就叫做nsproxy,這個count是引用基數,還有Mount文件系統的NameSpace,還有PID,剛才說有6個,唯一缺少的是User的NameSpace,它所屬于哪個UserNameSpace,實際上所有東西都是用在這幾個數據結構里面.
同時在Linux下編程比較多,會用到clone的函數,這里需要這么幾個參數,其中的flags參數就是剛才說的clone里面需要什么NameSpace就把相應的值傳到里面.接下來我們從源碼上分析一下clone系統調用是怎樣把各種NameSpace創建出來,在Docker里面怎么把內核里面把容器創造出來.
這是函數調用站的一個圖,首先是用戶傳到clone,平時咱們用Linux編程的時候用到clone,fork的話全都是0,傳到do-fork,復制到dup,在所有數據結構做復制,拷貝進程的證書,進程證書很有意思,如果這個cloneflags從一開始傳遞過來,會創建一個新的NameSpace.
這個函數很有意思,在Docker容器里面,一進去之后,一看咱們在里面已經入駐的選項,這里面有幾個Full-SET,把證書的權限全都是Full-SET,把所有權限全都付給Docker容器,實際上Linux的權限劃分一共有38個,38個每個全景都是一個位,所有的權限通過64位的數全部都能保存下來,實際上這個就是64位無符號整形的數,把所有的權限全都付給全部的權限.證書也屬于UserNameSpace,就屬于從上一步傳過來的這個.
NameSpace創立完了之后就該拷貝其他的五個NameSpace了,接下來執行,執行之后這幾個新的NameSpace也調相應的函數,把新創建的NameSpace傳到里面,也就是說這幾個創建出來的新的,比如UTS、IPC都是新創建出來的.
剛剛講完NameSpace,實際上就是把資源做一個資源隔離.咱們舉一個非常簡單的例子,就是以主機名稱做非常簡單的例子來看內核是怎么實現資源隔離的.
這個NameSpace就是主機的NameSpace一共有這么幾個成員,其中附名字的這塊就是Name,登錄了名字之后就保存在Name里面,這是相應的數據結構.這邊是現在有一個設置主機名稱,這邊進來之后會先檢查當前的進程是否有權限修改UTS所屬的User里面是否有這個權限,在創建進程的時候實際上已經看到本身給進程附加上所有的Full-SET.接下來檢查程度,把用戶傳過來的HostName拷貝到這個結構里.
我們來看登錄之后,內核怎么取?就調UTSName,把這個Name取下來,把Name直接拷貝到用戶空間,這個Name就是從用戶開始傳過來的,這是它的長度,把HostName拷貝到用戶空間里面.實際上它怎么做到資源隔離呢?實際上把不同的變量存到不同的NameSpace里面,每次設置的時候,都會從當前的進程里面的NameSpace里面去取.
這個權限檢查,能看到剛才有一個權限檢查,檢查當前UTS NameSpace所屬的UserNameSpace是否有權限,再往深一步怎么做?
首先把當前進程的證書以及需要在哪個NameSpace里面有傳到這個函數里面,有三個參數,一個是當前進程的證書,還有目標,我需要在這個NameSpace,要去檢查剛才說的64位,看這里面有沒有權限,如果說沒有,就返回權限不足,基本上在Linux里面每一次做權限檢查的時候都會調內核里面的這個函數,比如你進入一個你不該進入的目錄,它實際上也會調它.
下一步假如說你當前并不是在同一個NameSpace里邊,這邊有一個init-User-ns,一個是普通賬戶,登錄之后普通賬戶要鎖在NameSpace里面,也是這個init-User-NameSpace,它所有的權限都是滿的,普通用戶這邊是0,這邊檢查一下當前進程的User-NameSpace是不是附類,如果當前進程創建是目的User NameSpace的附類它擁有全部的權限.
這是整個跟NameSpace相關的系統調用,剛才unshare用得非常頻繁,它的作用是不需要啟動新進程就可以達到NameSpace隔離的效果.這個setes是已經存在的NameSpace,通過兩個Docker符號,當前進入PID,在文件系統里面創建自己的目錄,目錄名字就是以進程PID來命名的,可以看出來上面有這些號,這些號就會在這里面去用.
下面講Docker的ControlGroups,是做系統資源,比如CIO或者網絡的流量控制,可以把資源做切片,比現在Control ?Groups可以對容器的內存CPU做一些限制.
我覺得這個容器我不可能給它附100%的CPU資源,我就可以通過CGroups來限制它,像CPU,還有塊設備,還有網絡的,還有內存的,這是CGroups的術語,這是典型的CGroups用文件系統來實現的一個和內核交互的東西,我們可以設置CGroups,像寫一個文件一樣,比方我在這里邊新建一個CGroups,就是vsec.我可以限制里面有一些系統參數,我可以設置直接寫比如說5萬,寫到這個文件里邊,比如說cpu.cfs-quota-us,內核處理的時候就會直接限制CPU使用的百分比.
下面是一個例子,我可以寫這樣一個腳本,這個腳本就是寫的一個死循環,本身不做Control Groups是占用100%的CPU.
接下來通過CGroups直接寫到這個文件里邊的話,再把PID6814寫到tasks文件里面就可以直接變成50%,寫到這個文件里面,它是sys文件系統,實際上還是在內核調用還是虛擬文件系統能直接找到這個文件相當于函數,在這個里面把進程的PID加到列表里邊,當進程使用CPU資源的時候就會從這5萬里邊去限制CPU應該管理員希望占用的百分比.
AUFS時間關系,先略過去,實際上相比Linux啟動的時候,就好像Docker在啟動進項的過程,它的過程就好像Linux啟動內核初始化的時候用的步驟,實際上是一樣的.時間關系,我把這塊先略過去.
說幾個安全策略方面的東西.
比如DockerSwarm有一個集群管理配置問題,配置失誤在哪?DockerSwarm會監聽一個端口,2375,官方配置綁定的IP是0.0.0.0,假如你要這么配置,隨便一個人都會遠程訪問Docker容器.這是DockerSwarm集群的圖,下面從Docker文章里面出來,綁定的IP地址就是0.0.0.0,任何人都可以在網上直接接入.
這是Linux權限模型,大家可以看到Docker本身在啟動的時候會禁用一些權限,實際上有的權限即使不禁用,Docker的使用者在容器里面也是沒有辦法用的,為什么?
舉個例子,就比方說我想往內核里邊加一個內核模塊,這個模塊會調這么一個函數,把這個權限能否加模塊的權限傳到里面,又會去掉它,這個東西就會檢查把目的的init-User-ns是否有CAP-SYS這個權限.
Docker所屬的User-ns和init-User-ns不一樣,首先這一塊條件就是不滿足的,因為本身它倆并不是在同一個NameSpace里邊.這邊要求在這個NameSpace里邊,在init-User-ns里邊,到了這一步之后直接返回權限不足.
咱們想一想也能知道,Docker肯定是不允許你在容器里面,即使在容器里面是入權限也不可能加載一個模塊進去,加載一個模塊就相當于你這樣一個權限了,你有這么大的權限,你可以在整個物理機上面做任何你想干的事,這肯定是不被允許的,即使Docker把這個權限附給進程了,進程也是沒有辦法用的.
這是DockerLinux另外一個安全特性,它可以限制容器里面所調動的系統API,這個東西需要看內核是否支持這個選項,現在默認全都是支持這個權限,全都是默認啟用的.
這是Docker限制44個系統調用,比如說其中有一個設置系統實時鍵,這個肯定會被禁用,為什么?
因為Docker本身沒有關系時間的NameSpace,沒有時間做容器的隔離,要是這個容器把系統時間改了,肯定是影響其他容器的.
這是Docker的Seccomp的系統文件,是一個白名單,在內核里面以什么樣的方式來實現的,時間關系,這邊也得跳過去.
最后我給大家展示一下我們團隊在研究演示Docker逃逸的演示.
文章來自微信公眾號:云計算開源產業聯盟
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/4136.html