應(yīng)對SUID程序帶來隱患,增強(qiáng)Docker程序安全
Docker的安全問題一直是大家關(guān)心的熱點(diǎn),本文重點(diǎn)提出啟用SUID的程序所帶來的安全隱患,提出了對應(yīng)的解決方法,從而加強(qiáng)Docker的安全保障,值得一讀。
大部分人考慮強(qiáng)化Docker容器的時(shí)候,首先想到的是將默認(rèn)用戶設(shè)置為非root賬戶。在黑客攻擊容器之前,他們需要得到該容器的root權(quán)限。如果以非root賬戶運(yùn)行容器就會使攻擊更為困難。
運(yùn)行docker run或者docker create命令時(shí),通過-u或者-user參數(shù),可以以任意已經(jīng)存在在目標(biāo)鏡像里的非root用戶啟動容器??梢韵扔胐ocker history查看容器命令歷史記錄,在其中查找adduser命令,這樣可以查出現(xiàn)存用戶??梢圆榭碪SER命令確定是否設(shè)定了默認(rèn)用戶?;蛘撸苯訌溺R像啟動一個(gè)容器并進(jìn)入shell命令行直接手動檢查。如果你不喜歡這么查來查去,通常也可以直接使用“nobody”用戶。
我覺得Tutum最近不會提供特定的接口幫助查看正在容器里運(yùn)行的用戶。因此如果你想要以非root用戶運(yùn)行,必須確保你想啟動的鏡像服務(wù)的默認(rèn)用戶設(shè)置成了這個(gè)非root用戶。
以非root用戶運(yùn)行是一個(gè)好的開始,但是還可以做得更好。其中一件有趣的事情是去取消文件里SUID參數(shù)的設(shè)置,或者直接從鏡像里刪除帶這個(gè)參數(shù)的文件?,F(xiàn)在你可能會問:“SUID參數(shù)到底是什么?”
SUID參數(shù)是指Linux文件權(quán)限。大多數(shù)Linux用戶對Linux文件權(quán)限都有一定的了解。較為熟知的9參數(shù)描述了文件擁有者,組以及其他用戶對某個(gè)特定文件享有的權(quán)限。比如:
- "-rwxr-xr-x 1 root root" (or 755)
- 文件擁有者可以讀、寫和執(zhí)行該文件
- 在文件組里的用戶可以讀和執(zhí)行該文件
- 其他任何用戶可以讀和執(zhí)行該文件
SUID參數(shù)是可執(zhí)行參數(shù)的細(xì)化。它告訴Linux在執(zhí)行該文件時(shí),將活動的組或用戶設(shè)置為該文件的擁有組或用戶。
- "-rwsr-xr-x 1 root root"
或者
- "-rwxr-sr-x 1 root root"
很多時(shí)候普通用戶需要訪問某個(gè)需要特定權(quán)限才能訪問的程序。最常見的時(shí)ping命令。我喜歡這個(gè)例子因?yàn)樗袝r(shí)候顯得很微不足道而無害。ping要求root權(quán)限因?yàn)樗褂肐CMP協(xié)議。一個(gè)典型的Linux安裝后會包含多個(gè)這樣的工具。在ubuntu:latest鏡像里有22個(gè)帶有SUID設(shè)置的程序。
- /sbin/unix_chkpwd
- /usr/bin/chage
- /usr/bin/passwd
- /usr/bin/mail-touchlock
- /usr/bin/mail-unlock
- /usr/bin/gpasswd
- /usr/bin/crontab
- /usr/bin/chfn
- /usr/bin/newgrp
- /usr/bin/sudo
- /usr/bin/wall
- /usr/bin/mail-lock
- /usr/bin/expiry
- /usr/bin/dotlockfile
- /usr/bin/chsh
- /usr/lib/eject/dmcrypt-get-device
- /usr/lib/pt_chown
- /bin/ping6
- /bin/su
- /bin/ping
- /bin/umount
- /bin/mount
如下例子展示SUID參數(shù)如何工作。有如下Dockerfile:
- FROM ubuntu:latest
- RUN chmod u+s /usr/bin/whoami
- RUN adduser --system --no-create-home --disabled-password --disabled-login --shell /bin/sh example
- USER example
- CMD printf "Container running as: %s\n" `id -u -n` && printf "Effectively running whoami as: %s\n" `whoami`
從這個(gè)Dockerfile構(gòu)建并運(yùn)行鏡像會得到如下輸出:
- docker build -t tutumblog/suid_whoami . \
- && docker run --rm tutumblog/suid_whoami
- …
- Container running as: example
- Effectively running whoami as: root
在這個(gè)例子里,我從基礎(chǔ)Ubuntu鏡像啟動,將whoami命令設(shè)置上SUID參數(shù)。然后為這個(gè)鏡像添加example用戶,并且設(shè)置其為從此鏡像創(chuàng)建出的容器的默認(rèn)用戶??梢钥闯鰡栴}是,展示了兩個(gè)不同的當(dāng)前用戶。當(dāng)example用戶執(zhí)行whoami時(shí),因?yàn)槠鋷в蠸UID參數(shù)設(shè)置,Linux用root用戶執(zhí)行它,所以顯示文件的擁有者是root。
現(xiàn)在很明顯whoami不是一個(gè)需要由其擁有者才能執(zhí)行的程序。實(shí)際上它顯示了錯(cuò)誤的結(jié)果?,F(xiàn)在需要解決的問題是:“在運(yùn)行時(shí)里我需要帶有SUID設(shè)置的程序嗎?”我認(rèn)為大部分時(shí)候的回答是:“不需要。”
我知道你能找到一些例子說明運(yùn)行時(shí)需要帶有SUID參數(shù)設(shè)置的程序。有些人需要crontab。有些人需要ping來診斷問題。但是如果這22個(gè)程序的其中某個(gè)程序有bug怎么辦?如果這個(gè)程序設(shè)置了SUID參數(shù),黑客又探測到這個(gè)bug,那么他們將控制整個(gè)容器。
取消SUID參數(shù)的設(shè)置就可以解決這個(gè)問題??梢钥紤]在Dockerfile里增加一行來取消鏡像里所有SUID參數(shù)的設(shè)置。如下示例:
- FROM ubuntu:latest
- RUN adduser --system --no-create-home --disabled-password --disabled-login --shell /bin/sh example
- RUN for i in `find / -perm +6000 -type f`; do chmod a-s $i; done
- USER example
- CMD /bin/bash
或者,可以直接刪除這些程序來解決問題:
- …
- RUN for i in `find / -perm +6000 -type f`; do rm -f $i; done
- …
容器是用來隔離而不是虛擬化的?;谶@一點(diǎn),Docker鏡像是用來提供應(yīng)用或服務(wù)啟動所需最小的文件集。如果你的確需要其中一些程序以root用戶運(yùn)行,那么可以選擇哪些容器需要加強(qiáng),哪些容器不需要。但是要意識到其中存在的風(fēng)險(xiǎn)。