1. 程式人生 > >從自身漏洞與架構缺陷,談Docker安全建設

從自身漏洞與架構缺陷,談Docker安全建設

作者介紹

林偉壕,網易遊戲資深運維工程師,先後在中國電信和網易遊戲從事資料網路、網路安全和遊戲運維工作。對Linux運維、虛擬化和網路安全防護等研究頗多,目前專注於網路安全自動化檢測、防禦系統構建。

與其它介紹Docker的文章不同,本文專注於分析Docker安全。第一部分介紹Docker存在的安全問題、整套Docker應用架構的安全基線以及安全規則,重頭戲是Docker安全規則的各種思路和方案,第一部分重點介紹Docker官方安全建議。第二部分是Docker安全規則的各種思路與方案的詳細實現,包括技術選型、應用部署、功能使用以及如何與企業或組織的Docker容器編排系統、倉庫整合等具體問題,這部分更多是介紹業界實現。

Docker簡介

Docker

按照Docker官方的介紹:Docker是世界領先的容器平臺。開發人員使用Docker在與同事協作程式碼時消除“在我的機器上工作”的問題。 運營商使用Docker在並行容器中並行執行和管理應用程式,以獲得更好的計算密度。企業使用Docker構建敏捷軟體交付管道,以更快,更安全,更可靠地為Linux和Windows Server應用程式提供新功能。挺拗口的,大概是這麼一回事。

說起容器,很容易想到虛擬機器,人們也熱衷於討論虛擬機器與容器的區別,那麼,本文也不能免俗,下面就來對比一下兩者,從而突出Docker容器的不同之處。

Docker與虛擬機器的區別

隔離與共享:

虛擬機器通過新增hypervisor層,虛擬出網絡卡,記憶體,CPU等虛擬硬體,再在其上建立客戶機,每個客戶機都有自己的系統核心。而docker容器則是通過隔離的方式,將檔案系統,程序,裝置,網路等資源進行隔離,再對許可權,CPU資源等進行控制,最終讓容器之間互不影響,容器無法影響宿主機。容器與宿主機共享核心,檔案系統,硬體等資源。

效能與損耗:

與虛擬機器相比,容器資源損耗要小得多。 同樣的宿主機下,能夠建立容器的數量要比虛擬機器多得多。

安全性:

但是虛擬機器的安全性要比容器好一些,要從虛擬機器突破到宿主機或其他虛擬機器,需要先突破hypervisor層,這是極其困難的。 而docker容器與宿主機共享核心,檔案系統等資源,更有可能對其他容器,宿主機產生影響。

容器

Docker存在的安全問題

下面進入正題,從攻擊樹上來講,Docker的安全問題如下圖所示:

Docker

Docker自身漏洞

Docker作為一款應用本身實現上會有程式碼缺陷。CVE官方記錄docker歷史版本共有超過20項漏洞,參見https://docs.docker.com/engine/security/non-events/。主要有程式碼執行,許可權提升,資訊洩露,繞過這幾類。現在Docker已經到了17.03版本,版本更迭非常快,docker使用者最好將docker升級為最新版本。

Docker源問題

Docker提供了docker hub可以讓使用者上傳建立的映象,以便其他使用者下載,快速搭建環境。但同時也帶來了一些安全問題。下載的映象被惡意植入後門,傳輸的過程中映象被篡改, 映象所搭建的環境是否本身就包含漏洞等等,不一而足。主要介紹下面三種:

1.黑客上傳惡意映象

如果有黑客在製作的映象中植入木馬,後門等惡意軟體,那麼環境從一開始就已經不安全了,後續更沒有什麼安全可言。

2.映象使用有漏洞的軟體

據一些報告顯示,hub上能下載的映象裡面,75%的映象都安裝了有漏洞的軟體,所以下載映象後,需要檢查裡面軟體的版本資訊,對應的版本是否存在漏洞,並及時更新打上補丁。

3.中間人攻擊篡改映象

映象在傳輸過程中可能被篡改,目前新版本的Docker已經提供了相應的校驗機制來預防這個問題。

Docker架構缺陷與安全機制

由Docker本身的架構與機制可能產生的問題,這一攻擊場景主要產生在黑客已經控制了宿主機上的一些容器(或者通過在公有云上建立容器的方式獲得這個條件),然後對宿主機或其他容器發起攻擊來產生影響。

容器之間的區域網攻擊

同一主機上的容器之間可以構成區域網,因此針對區域網的ARP欺騙,嗅探,廣播風暴等攻擊方式便可以用上。所以在一個主機上部署多個容器需要合理的配置網路,設定iptable規則。

DDoS攻擊耗盡資源

cgroups安全機制就是要防止此類攻擊的,不要為單一的容器分配過多的資源即可避免此類問題。

呼叫有漏洞的系統呼叫

我們都知道Docker與虛擬機器的一個區別就是,Docker與宿主公用一個作業系統核心,一旦宿主核心存在可以橫向越權或者提權漏洞,那麼儘管Docker使用普通使用者執行,一旦容器被入侵,攻擊者還是可以利用核心漏洞逃逸到宿主,做更多事情。

共享root

如果以root許可權執行容器,容器內的root使用者也就擁有了宿主機的root許可權。

未隔離的檔案系統

雖然Docker已經對檔案系統進行隔離,但是有一些重要的系統檔案暫時沒有被隔離,如/sys, /proc/sys, /proc/bus等。

Docker安全基線

這部分結合了Docker官方文件與陳愛珍的《如何打造安全的容器雲平臺》整理而成,從核心、主機、網路、映象、容器以及其他等6大方面總結了Docker安全基線標準。

核心級別
  • 及時更新核心
  • User NameSpace(容器內的root許可權在容器之外處於非高許可權狀態)
  • Cgroups(對資源的配額和度量)
  • SELiux/AppArmor/GRSEC(控制檔案訪問許可權)
  • Capability(許可權劃分)
  • Seccomp(限定系統呼叫)
  • 禁止將容器的名稱空間與宿主機程序名稱空間共享
主機級別
  • 為容器建立獨立分割槽
  • 僅執行必要的服務
  • 禁止將宿主機上敏感目錄對映到容器
  • 對Docker守護程序、相關檔案和目錄進行審計
  • 設定適當的預設檔案描述符數
  • 使用者許可權為root的Docker相關檔案的訪問許可權應該為644或者更低許可權
  • 週期性檢查每個主機的容器清單,並清理不必要的容器
網路級別
  • 通過iptables設定規則實現禁止或允許容器之間網路流量
  • 允許Dokcer修改iptables
  • 禁止將Docker繫結到其他IP/Port或者Unix Socket
  • 禁止在容器上對映特權埠
  • 容器上只開放所需要的埠
  • 禁止在容器上使用主機網路模式
  • 若宿主機有多個網絡卡,將容器進入流量繫結到特定的主機網絡卡上
映象級別
  • 建立本地映象倉庫伺服器
  • 映象中軟體都為最新版本
  • 使用可信映象檔案,並通過安全通道下載
  • 重新構建映象而非對容器和映象打補丁
  • 合理管理映象標籤,及時移除不再使用的映象
  • 使用映象掃描
  • 使用映象簽名
容器級別
  • 容器最小化,作業系統映象最小集
  • 容器以單一主程序的方式執行
  • 禁止privileged標記使用特權容器
  • 禁止在容器上執行ssh服務
  • 以只讀的方式掛載容器的根目錄系統
  • 明確定義屬於容器的資料碟符
  • 通過設定on-failure限制容器嘗試重啟的次數
  • 限制在容器中可用的程序樹,以防止fork bomb
其他設定
  • 定期對宿主機系統及容器進行安全審計
  • 使用最少資源和最低許可權執行容器
  • 避免在同一宿主機上部署大量容器,維持在一個能夠管理的數量
  • 監控Docker容器的使用,效能以及其他各項指標
  • 增加實時威脅檢測和事件響應功能
  • 使用中心和遠端日誌收集服務

Docker安全規則

Docker安全規則其實屬於Docker安全基線的具體實現,不過對於Docker官方提出的方案本文會直接給出實現方式,而對於第三方或者業界使用的方案,則只是介紹基本規則,具體實現方案會在本系列下部分介紹。

容器最小化

僅在容器中執行必要的服務,像ssh等服務是絕對不能開啟的。使用以下方式來管理你的容器:

docker exec -it mycontainer bash

Docker remote api訪問控制

Docker的遠端呼叫API介面存在未授權訪問漏洞,至少應限制外網訪問。如果可以,建議還是使用socket方式訪問。

建議監聽內網ip或者localhost,docker daemon啟動方式:

docker -d -H uninx:///var/run/docker.sock  -H tcp://10.10.10.10:2375#或者在docker預設配置檔案指定

other_args=” -H  unix:///var/run/docker.sock -H tcp://10.10.10.10:2375″

然後在宿主iptables上做訪問控制

*filter:

HOST_ALLOW1 – [0:0]

-A HOST_ALLOW1 -s 10.10.10.1/32 -j ACCEPT

-A HOST_ALLOW1 -j DROP

-A INPUT -p tcp -m tcp -d 10.10.10.10 –port 2375 -j HOST_ALLOW1

限制流量流向

可以使用以下Iptables過濾器限制Docker容器的源IP地址範圍與外界通訊。

Iptables -A FORWARD -s <source_ip_range> -j REJECT –reject-with icmp-admin-prohibited

Iptables -A FORWARD -i docker0 -o eth0 -j DROP

Iptables-A FORWARD -i docker0 -o eth0 -m state –state ESTABLISHED -j ACCEPT

使用普通使用者啟動Docker服務

截至Docker 1.10使用者名稱空間由Docker守護程式直接支援。此功能允許容器中的root使用者對映到容器外部的非uid-0使用者,這可以幫助減輕容器中斷的風險。此功能可用,但預設情況下不啟用。

1、使用使用者對映

要解決特定容器中的使用者0在宿主系統上等於root的問題,LXC允許您重新對映使用者和組ID。配置檔案條目如下所示:

lxc.id_map = u 0 100000 65536

lxc.id_map = g 0 100000 65536

這將容器中的前65536個使用者和組ID對映到主機上的100000-165536。主機上的相關檔案是/etc/subuid和/etc/subgid。此對映技術命名為從屬ID,因此稱為“子”字首。

對於Docker,這意味著將其作為-lxc-conf引數新增到docker run:

docker run -lxc-conf =”lxc.id_map = u 0 100000 65536″ -lxc-conf =”lxc.id_map = g 0 100000 65536″

2、啟動容器時不帶–privileged引數

docker run -it debian8:standard /bin/bash

檔案系統限制

掛載的容器根目錄絕對只讀,而且不同容器對應的檔案目錄許可權分離,最好是每個容器在宿主上有自己單獨分割槽。

su con1

docker run -v dev:/home/mc_server/con1 -it debian8:standard /bin/bash

su con2

docker run -v dev:/home/mc_server/con2 -it debian8:standard /bin/bash

映象安全

如下圖所示,在映象倉庫客戶端使用證書認證,對下載的映象進行檢查 ,通過與CVE資料庫同步掃描映象,一旦發現漏洞則通知使用者處理,或者直接阻止映象繼續構建。

如果使用的是公司自己的映象源,可以跳過此步;否則至少需要驗證baseimage的md5等特徵值,確認一致後再基於baseimage進一步構建。

一般情況下,我們要確保只從受信任的庫中獲取映象,並且不要使用–insecure-registry=[]引數。具體實現我們在漏洞掃描部分一塊介紹。

映象安全

Docker client端與Docker Daemon的通訊安全

按照Docker官方的說法,為了放置鏈路劫持、會話劫持等問題導致Docker通訊時被中間人攻擊,c/s兩端應該通過加密方式通訊。

docker –tlsverify –tlscacert=ca.pem –tlscert=server-cert.pem –tlskey=server-key.pem  -H=0.0.0.0:2376

資源限制

限制容器資源使用,最好支援動態擴容,這樣既可以儘可能降低安全風險,也不影響業務。下面是使用樣例,限制cpu使用第2核、分配2048:

docker run -tid –name ec2 –cpuset-cpus 3 –cpu-shares 2048 -memory 2048m –rm –blkio-weight 100 –pids–limit 512

更多限制可以參考Docker官方說明:

宿主及時升級核心漏洞

使用Docker容器對外提供服務時,還要考慮宿主故障或者需要升級核心的問題。這時為了不影響線上業務,Docker容器應該支援熱遷移,這個可以納入容器排程系統的功能設計中。此外,還應考慮後續的核心升級方案規劃、執行以及回遷方案等。

避免Docker容器中資訊洩露

就像之前Github上大量洩露個人或企業各種賬號密碼的問題,我們一般使用dockerfile或者docker-compose檔案建立容器,如果這些檔案中存在賬號密碼等認證資訊,一旦Docker容器對外開放,則這些宿主機上的敏感資訊也會隨之洩露。因此可以通過以下方式檢查容器建立模板的內容:

# check created users

grep authorized_keys $dockerfile

# check OS users

grep “etc/group” $dockerfile

# Check sudo users

grep “etc/sudoers.d” $dockerfile

# Check ssh key pair

grep “.ssh/.*id_rsa” $dockerfile

# Add your checks in below

安裝安全加固

如果可能,使用安全的Linux核心、核心補丁。如SELinux,AppArmor,GRSEC等,都是Docker官方推薦安裝的安全加固元件。

如果先前已經安裝並配置過SELinux,那麼可以在容器使用setenforce 1來啟用它。Docker守護程序的SELinux功能預設是禁用的,需要使用–selinux-enabled來啟用。容器的標籤限制可使用新增的—-security-opt載入SELinux或者AppArmor的策略進行配置,該功能在Docker版本1.3[9]引入。例如:

docker run –security-opt=secdriver:name:value -i -t centos bash

SELinux的相關選項:

SELinux

AppArmor的選項:

– -secutity-opt =”apparmor:PROFILE”(設定AppArmor配置檔案)

GRSEC的選項:

gradm -F -L /etc/grsec/learning.logs

GRSEC的更多說明請參考:https://en.wikibooks.org/wiki/Grsecurity

限制系統命令呼叫

1.系統呼叫層面

Linux系統呼叫列表見:

http://www.ibm.com/developerworks/cn/linux/kernel/syscall/part1/appendix.html

Seccomp(secure computing mode),就是安全計算模式,這個模式可以設定容器在對系統進行呼叫時進行一些篩選,也就是所謂的白名單。它可以去指定允許容器使用哪些的呼叫,禁止容器使用哪些呼叫,這樣就可以增強隔離,它其實也是訪問控制的一個部分。

2.函式呼叫層面

通過使用“–security-optseccomp=<profile>”標記來指定自定義的seccomp描述檔案:

$ docker run -d –security-opt seccomp:allow:clock_adjtime ntpd

這條命令將會允許容器內使用clock_adjtime呼叫

$docker run -d –security-opt seccomp:deny:getcwd /bin/sh

這條命令將會禁止容器內執行的shell查詢當前自己所在的目錄

shell

在沒有預設secconf配置檔案的情況下執行,可以通過unconfined執行配置不在預設seccomp配置檔案的容器。

$ docker run –rm -it –security-opt seccomp =ulimit-debian:jessie \ unshare –map-root-user –user sh -c whoami

suid和guid限制

SUID和GUID程式在受攻擊導致任意程式碼執行(如緩衝區溢位)時將非常危險,因為它們將執行在程序檔案所有者或組的上下文中。如果可能的話,使用特定的命令列引數減少賦予容器的能力,阻止SUID和SGID生效。

docker run -it –rm –cap-drop SETUID –cap-drop SETGID

還有種做法,可以考慮在掛載檔案系統時使用nosuid屬性來移除掉SUID能力。最後一種做法是,刪除系統中不需要的SUID和GUID程式。這類程式可在Linux系統中執行以下命令而找到:

find / -perm -4000 -exec ls -l {} \; 2>/dev/null

find / -perm -2000 -exec ls -l {} \; 2>/dev/null

然後,可以使用類似於下面的命令將移除SUID和GUID檔案許可權:

sudo chmod u-s filename sudo chmod -R g-s directory

能力限制

儘可能降低Linux能力。

Docker預設的能力包括:chown、dac_override、fowner、kill、setgid、setuid、setpcap、net_bind_service、net_raw、sys_chroot、mknod、setfcap、和audit_write。在命令列啟動容器時,可以通過–cap-add=[]或–cap-drop=[]進行控制。例如:

docker run –cap-drop setuid –cap-drop setgid -ti <container_name> /bin/sh

此功能在Docker 1.2版本引入。

多租戶環境

由於Docker容器核心的共享性質,無法在多租戶環境中安全地實現責任分離。建議將容器執行在沒有其它目的,且不用於敏感操作的宿主上。可以考慮將所有服務遷移到Docker控制的容器城。可能的話,設定守護程序使用–icc=false,並根據需要在docker run時指定-link,或通過—-export=port暴露容器的一個埠,而不需要在宿主上釋出。將相互信任的容器的組對映到不同機器上。

完全虛擬化

使用一個完全虛擬化解決方案來容納Docker,如KVM。如果容器內的核心漏洞被發現,這將防止其從容器擴大到宿主上。類似Docker-in-Docker工具,Docker映象可以巢狀來提供該KVM虛擬層。

日誌分析

收集並歸檔與Docker相關的安全日誌來達到稽核和監控的目的,一般建議使用rsyslog或stdout+ELK的方式進行日誌收集、儲存與分析,因為Docker本身要求輕量,所以不建議像虛擬機器或者物理機上安裝安全agent,這時實時威脅檢測和事件響應功能就要依賴實時日誌傳輸和分析了。可以在宿主上使用以下命令在容器外部訪問日誌檔案:

docker run -v /dev/log:/dev/log <container_name> /bin/sh

使用Docker內建命令:

docker logs … (-f to follow log output)

日誌檔案也可以匯出成一個壓縮包實現持久儲存:docker export

漏洞掃描

前面的映象安全,跟這裡的漏洞掃描關聯很密切,可以使用相同的工具去實現安全掃描,不過漏洞掃描更傾向於外部檢測,映象安全則需要映象倉庫和CI系統聯動,始終不是一回事,所以分來介紹。

下面介紹5款用於Docker漏洞掃描的工具,它們各有千秋,從映象到容器,從宿主到容器,從dockerfile到docker-compose,從安全基線檢查與漏洞發現,從容器安全到效能優化,均有覆蓋。

1.docker-slim

參考:https://github.com/docker-slim/docker-slim

建立小容器需要大量的巫術魔法,它可以是相當痛苦的。你不應該丟掉你的工具和你的工作流程。使用Docker應該很容易。docker-slim是一個容器的魔法減肥藥。它將使用靜態和動態分析為你的應用程式建立一個緊湊的容器。

2.Docker Bench for Security

參考:https://github.com/docker/docker-bench-security

Docker Bench for Security是一個指令碼,用於檢查在生產環境中部署Docker容器的幾十個常見的最佳實踐,測試都是自動化的,受CIS Docker 1.13基準的啟發而來。

3.Clair

參考:https://github.com/coreos/clair

Clair是一個用於靜態分析應用程式容器(目前包括appc和Docker)中的漏洞的開源專案。基於K8S,將映象上傳到clair所在機器掃描即可。從已知的一組源連續匯入漏洞資料,並與容器映像的索引內容相關聯,以便產生威脅容器的漏洞的列表。當漏洞資料在上游發生變化時,可以傳遞通知,並且API會查詢以提供漏洞的先前狀態和新狀態以及受這兩者影響的影象。

4.Container-compliance

參考:https://github.com/OpenSCAP/container-compliance

Container-compliance是基於OpenSCAP的用於評估映象、容器合規性的資源和工具。

5.Lynis

參考:https://cisofy.com/lynis/plugins/docker-containers/

Lynis本身是一套Linux/Unix系統安全審計的shell指令碼,執行時系統消耗很低。Lynis-docker是Lynis的一個外掛,這個外掛收集關於Docker配置和容器的資訊。

埠掃描

很多人認為,容器被入侵帶來的風險,遠比不上物理機和傳統虛擬機器,於是他們直接把Docker容器對外網開放,而且不配置任何訪問控制。另外,也會存在宿主iptables錯誤調導致容器直接對外開放的問題存在,於是,這時針對容器進行快速批量的埠快速掃描顯得很有必要。目前Nmap/Masscan這兩款工具用的比較多。

Nmap支援tcp/udp埠掃描以及自定義外掛掃描任意漏洞,是最著名、應用最廣的埠掃描器。masscan的掃描結果類似於nmap,在內部,它更像scanrand, unicornscan, and ZMap,採用了非同步傳輸的方式。它和這些掃描器最主要的區別是,它比這些掃描器更快。

參考:https://github.com/robertdavidgraham/masscan

總結

上面介紹了很多配置、工具,如果要應用到生產環境,還是需要大量調研的,所以本文的下半部分會結合將它們聯動起來,深入到應用部署、功能使用以及如何與企業或組織的Docker容器編排系統、倉庫整合等具體實現,形成一套企業級Docker安全解決方案,敬請期待。

文章來自微信公眾號: DBAplus社群