用 SELinux 保護你的容器
當有些事情在你的 Linux 環境中不能正常工作時,最簡單的方法就是禁用 安全增強型 Linux (SELinux)。而當它突然可以工作了,你就會忘記了禁用這件事 —— 這是一個常見的陷阱,意味著你已經失去了一個非常強大的安全工具。
隨著容器、微服務和分散式架構的興起,威脅也在上升。這是由於一個老的、眾所周知的問題:速度。容器的優勢在於它們能讓你快速行動,做更多的事情,並迅速改變。這意味著容器的採用已經飛速發展,但它所提供的速度也意味著你會遇到更多的問題和漏洞。當你越來越快地做更多的事情時,這自然會發生。
如何減輕威脅
正如孫子所說,「不戰而屈人之兵」。當涉及到容器的基本防禦時,這句話真的很有共鳴。為了避免問題(戰鬥),確保你的容器主機是安全的,你可以使用 SELinux 作為你的第一道防線。
SELinux 是一個開源項目,於 2000 年發布,2003 年集成到 Linux 內核中。根據 紅帽公司的解釋,「SELinux 是 Linux 系統 的一個安全架構,允許管理員對誰可以訪問系統有更多的控制。它最初是由美國國家安全局(NSA)開發的,是使用 Linux 安全模塊(LSM)對 Linux 內核 的一系列補丁。」
開始吧
當你想到容器時,首先想到的可能是 Docker。Docker 在 2013 年出現後掀起了一場容器採用革命。它是容器爆炸性流行的主要原因之一,但如上所述,大量採用增加了用戶對安全風險的脆弱性。
在你用 SELinux 保護你的 Docker 容器之前,你需要設置一些東西。
前置條件
- 安裝並配置了 CentOS 8/RHEL 8。
- 安裝並配置好 Docker CE
- 創建兩個賬戶:root 和 非 root 用戶(下面的例子中是
mcalizo
)。
如果你需要在你的 RHEL 8/CentOS 8 伺服器上設置 Docker,你可以按照這些 說明。如果你運行的是 RHEL 8,你需要在開始之前刪除預裝的 Podman 和 runc 包。
首先,確保 SELinux 被啟用:
[mcalizo@Rhel82 ~]$ sestatus
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Memory protection checking: actual (secure)
Max kernel policy version: 31
[mcalizo@Rhel82 ~]$
然後,驗證你的操作系統版本和 Docker 正在運行。以 root 身份登錄並運行:
[root@rhel82 ~]# cat /etc/redhat-release
Red Hat Enterprise Linux release 8.2 (Ootpa)
[root@rhel82 ~]#
[root@rhel82 ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2020-10-28 19:10:14 EDT; 15s ago
Docs: https://docs.docker.com
Main PID: 30768 (dockerd)
Tasks: 8
Memory: 39.0M
CGroup: /system.slice/docker.service
└─30768 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
Oct 28 19:10:13 rhel82.home.labs.com dockerd[30768]: time="2020-10-28T19:10:13.889602941-04:00" level=error msg=">
Oct 28 19:10:13 rhel82.home.labs.com dockerd[30768]: time="2020-10-28T19:10:13.903413613-04:00" level=warning msg>
Oct 28 19:10:13 rhel82.home.labs.com dockerd[30768]: time="2020-10-28T19:10:13.903427451-04:00" level=warning msg>
Oct 28 19:10:13 rhel82.home.labs.com dockerd[30768]: time="2020-10-28T19:10:13.903538271-04:00" level=info msg="L>
Oct 28 19:10:14 rhel82.home.labs.com dockerd[30768]: time="2020-10-28T19:10:14.132060506-04:00" level=info msg="D>
Oct 28 19:10:14 rhel82.home.labs.com dockerd[30768]: time="2020-10-28T19:10:14.308943088-04:00" level=info msg="L>
Oct 28 19:10:14 rhel82.home.labs.com dockerd[30768]: time="2020-10-28T19:10:14.319438549-04:00" level=info msg="D>
Oct 28 19:10:14 rhel82.home.labs.com dockerd[30768]: time="2020-10-28T19:10:14.319570298-04:00" level=info msg="D>
Oct 28 19:10:14 rhel82.home.labs.com dockerd[30768]: time="2020-10-28T19:10:14.333419209-04:00" level=info msg="A>
Oct 28 19:10:14 rhel82.home.labs.com systemd[1]: Started Docker Application Container Engine
檢查你的 Docker 版本:
[root@rhel82 ~]# docker --version
Docker version 19.03.13, build 4484c46d9d
黑掉主機
了解一個問題的最好方法之一就是去體驗它。因此,我將告訴你,如果你的安全設置不當,向 Docker 主機注入惡意代碼是多麼容易。
為了能夠在 Docker 主機上做壞事,「惡意」的非 root 用戶(本教程中為 mcalizo
)必須是可以實例化 Docker 容器的組的成員。
首先,確認 mcalizo
用戶屬於哪個組:
[root@Rhel82 ~]# groups mcalizo
mcalizo : mcalizo
輸出顯示,mcalizo
只屬於它自己的組。這意味著 mcalizo
不能實例化 Docker 容器,如果它試圖這樣做,將會得到這個錯誤:
[mcalizo@Rhel82 ~]$ docker run -it --rm centos:latest /bin/sh
docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.40/containers/create: dial unix /var/run/docker.sock: connect: permission denied.
See 'docker run --help'.
要允許 mcalizo
實例化容器,將用戶加入 docker
組:
[root@Rhel82 ~]# usermod -G docker -a mcalizo
[root@Rhel82 ~]# groups mcalizo
mcalizo : mcalizo docker
接下來,部署一個 fedora:latest
的容器,並登錄到實例化的容器中去探索它:
[mcalizo@Rhel82 ~]$ docker run -it --rm fedora:latest /bin/sh
Unable to find image 'fedora:latest' locally
latest: Pulling from library/fedora
ee7e89337106: Pull complete
Digest: sha256:b9ec86d36fca7b1d3de39cd7c258e8d90c377d312c21a7748071ce49069b8db4
Status: Downloaded newer image for fedora:latest
sh-5.0# cat /etc/redhat-release
Fedora release 33 (Thirty Three)
當你登錄到新創建的容器時,你可以看到你是以 root 身份自動登錄的:
sh-5.0# whoami
root
sh-5.0#
作為 root
用戶,你可以在這個容器中做任何事情,這意味著你可以利用容器主機,做很多破壞。因為你可以實例化一個容器,即使你不屬於主機的 sudoers 賬戶,你也可以對主機做一些事情。
退出你剛剛創建的容器,並創建一個新的容器來演示這個漏洞:
[mcalizo@Rhel82 ~]$ docker run -it --rm -v /:/exploit fedora:latest /bin/bash
[root@131043f2e306 /]#
-v 選項 將 Docker 主機的 /
目錄掛載到 /exploit
目錄下的容器:
[root@131043f2e306 /]#ls exploit/
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
因為它已被掛載,你可以在 Docker 主機上做任何事情。例如,你可以刪除文件、編輯特定的配置來破害系統,甚至安裝木馬程序或其他惡意軟體來竊取重要信息。
為什麼會發生這種情況?
你可能想知道,既然 SELinux 處於強制模式,為什麼會出現這種情況?深入挖掘 SELinux,看看哪裡出了問題。
驗證 SELinux 是否有一個 Docker 上下文:
[mcalizo@Rhel82 ~]$ ps -eZ | grep docker
system_u:system_r:container_runtime_t:s0 30768 ? 00:00:04 dockerd
[mcalizo@Rhel82 ~]$
正如預期的那樣,它確實有。這意味著 SELinux 管理著 Docker 守護進程。檢查 Docker 守護進程,看看 SELinux 是否默認啟用:
[mcalizo@Rhel82 ~]$ docker info | grep Security -A3
Security Options:
seccomp
Profile: default
Kernel Version: 4.18.0-193.el8.x86_64
Docker 守護進程中的 SELinux 在默認情況下是 不啟用 的。 這就是問題所在!要解決這個問題,按 文檔 說明,通過更新或創建文件 /etc/docker/daemon.json
來啟用 SELinux 來控制和管理 Docker(你必須有 root 許可權才能這樣做):
[root@Rhel82 ~]# cat /etc/docker/daemon.json
{
"selinux-enabled": true
}
[root@Rhel82 ~]#
[root@Rhel82 ~]# systemctl restart docker
在創建或更新該文件並重啟 Docker 後,你應該看到 Docker 守護進程中啟用了 SELinux 支持:
[root@Rhel82 ~]# systemctl restart docker
[mcalizo@Rhel82 root]$ docker info | grep Security -A3
Security Options:
seccomp
Profile: default
selinux
[mcalizo@Rhel82 root]$
雖然仍然可以在你的 Docker 容器上掛載 Docker 主機中的特定文件系統,但不再允許更新或訪問該文件:
[mcalizo@Rhel82 root]$ docker run -it --rm -v /:/exploit fedora:latest /bin/bash
[root@ecb5836da1f6 /]# touch /exploit/etc/shadow.sh
touch: cannot touch '/exploit/etc/shadow.sh': Permission denied
[root@ecb5836da1f6 /]#
了解更多
你在容器世界中的第一道防線取決於你對容器主機的操作系統的設置有多強。有許多方法可以實現 Linux 的安全性,包括市場上可供選擇的方案,以增強你的安全態勢。
SELinux 是一個額外的安全層,默認情況下內置於 Linux 發行版 中。為了藉助它保護你的系統不被破壞,請確保 SELinux 保持開啟狀態。
如果你想了解更多,請參閱:
via: https://opensource.com/article/20/11/selinux-containers
作者:Mike Calizo 選題:lujun9972 譯者:wxy 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive