應對SUID程序帶來隱患,增強Docker程序安全
Docker的安全問題一直是大家關心的熱點,本文重點提出啟用SUID的程序所帶來的安全隱患,提出了對應的解決方法,從而加強Docker的安全保障,值得一讀。
大部分人考慮強化Docker容器的時候,首先想到的是將默認用戶設置為非root賬戶。在黑客攻擊容器之前,他們需要得到該容器的root權限。如果以非root賬戶運行容器就會使攻擊更為困難。
運行docker run或者docker create命令時,通過-u或者-user參數,可以以任意已經存在在目標鏡像里的非root用戶啟動容器。可以先用docker history查看容器命令歷史記錄,在其中查找adduser命令,這樣可以查出現存用戶。可以查看USER命令確定是否設定了默認用戶。或者,直接從鏡像啟動一個容器并進入shell命令行直接手動檢查。如果你不喜歡這么查來查去,通常也可以直接使用“nobody”用戶。
我覺得Tutum最近不會提供特定的接口幫助查看正在容器里運行的用戶。因此如果你想要以非root用戶運行,必須確保你想啟動的鏡像服務的默認用戶設置成了這個非root用戶。
以非root用戶運行是一個好的開始,但是還可以做得更好。其中一件有趣的事情是去取消文件里SUID參數的設置,或者直接從鏡像里刪除帶這個參數的文件。現在你可能會問:“SUID參數到底是什么?”
SUID參數是指Linux文件權限。大多數Linux用戶對Linux文件權限都有一定的了解。較為熟知的9參數描述了文件擁有者,組以及其他用戶對某個特定文件享有的權限。比如:
- "-rwxr-xr-x 1 root root" (or 755)
- 文件擁有者可以讀、寫和執行該文件
- 在文件組里的用戶可以讀和執行該文件
- 其他任何用戶可以讀和執行該文件
SUID參數是可執行參數的細化。它告訴Linux在執行該文件時,將活動的組或用戶設置為該文件的擁有組或用戶。
- "-rwsr-xr-x 1 root root"
或者
- "-rwxr-sr-x 1 root root"
很多時候普通用戶需要訪問某個需要特定權限才能訪問的程序。最常見的時ping命令。我喜歡這個例子因為它有時候顯得很微不足道而無害。ping要求root權限因為它要使用ICMP協議。一個典型的Linux安裝后會包含多個這樣的工具。在ubuntu:latest鏡像里有22個帶有SUID設置的程序。
- /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參數如何工作。有如下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`
從這個Dockerfile構建并運行鏡像會得到如下輸出:
- docker build -t tutumblog/suid_whoami . \
- && docker run --rm tutumblog/suid_whoami
- …
- Container running as: example
- Effectively running whoami as: root
在這個例子里,我從基礎Ubuntu鏡像啟動,將whoami命令設置上SUID參數。然后為這個鏡像添加example用戶,并且設置其為從此鏡像創建出的容器的默認用戶。可以看出問題是,展示了兩個不同的當前用戶。當example用戶執行whoami時,因為其帶有SUID參數設置,Linux用root用戶執行它,所以顯示文件的擁有者是root。
現在很明顯whoami不是一個需要由其擁有者才能執行的程序。實際上它顯示了錯誤的結果。現在需要解決的問題是:“在運行時里我需要帶有SUID設置的程序嗎?”我認為大部分時候的回答是:“不需要。”
我知道你能找到一些例子說明運行時需要帶有SUID參數設置的程序。有些人需要crontab。有些人需要ping來診斷問題。但是如果這22個程序的其中某個程序有bug怎么辦?如果這個程序設置了SUID參數,黑客又探測到這個bug,那么他們將控制整個容器。
取消SUID參數的設置就可以解決這個問題。可以考慮在Dockerfile里增加一行來取消鏡像里所有SUID參數的設置。如下示例:
- 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
- …
容器是用來隔離而不是虛擬化的。基于這一點,Docker鏡像是用來提供應用或服務啟動所需最小的文件集。如果你的確需要其中一些程序以root用戶運行,那么可以選擇哪些容器需要加強,哪些容器不需要。但是要意識到其中存在的風險。