用 SELinux 保护你的容器
SELinux 容器

> 
> 黑掉你的系统，了解为什么配置 SELinux 作为你的第一道容器防线是很重要的。
> 
> 
> 


![](/data/attachment/album/202203/02/093614t53cfb857841qzzk.jpg "Three closed doors")


当有些事情在你的 Linux 环境中不能正常工作时，最简单的方法就是禁用<ruby> 安全增强型 Linux <rt>  Security-Enhanced Linux </rt></ruby>（[SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux)）。而当它突然可以工作了，你就会忘记了禁用这件事 —— 这是一个常见的陷阱，意味着你已经失去了一个非常强大的安全工具。


随着容器、微服务和分布式架构的兴起，威胁也在上升。这是由于一个老的、众所周知的问题：速度。容器的优势在于它们能让你快速行动，做更多的事情，并迅速改变。这意味着容器的采用已经飞速发展，但它所提供的速度也意味着你会遇到更多的问题和漏洞。当你越来越快地做更多的事情时，这自然会发生。


### 如何减轻威胁


正如孙子所说，“不战而屈人之兵”。当涉及到容器的基本防御时，这句话真的很有共鸣。为了避免问题（战斗），确保你的容器主机是安全的，你可以使用 SELinux 作为你的第一道防线。


SELinux 是一个开源项目，于 2000 年发布，2003 年集成到 Linux 内核中。根据 [红帽公司的解释](https://www.redhat.com/en/topics/linux/what-is-selinux)，“SELinux 是 [Linux 系统](https://www.redhat.com/en/topics/linux/what-is-linux) 的一个安全架构，允许管理员对谁可以访问系统有更多的控制。它最初是由美国国家安全局（NSA）开发的，是使用 Linux 安全模块（LSM）对 [Linux 内核](https://www.redhat.com/en/topics/linux/what-is-the-linux-kernel) 的一系列补丁。”


### 开始吧


当你想到容器时，首先想到的可能是 [Docker](https://opensource.com/resources/what-docker)。Docker 在 2013 年出现后掀起了一场容器采用革命。它是容器爆炸性流行的主要原因之一，但如上所述，大量采用增加了用户对安全风险的脆弱性。


在你用 SELinux 保护你的 Docker 容器之前，你需要设置一些东西。


#### 前置条件


* 安装并配置了 CentOS 8/RHEL 8。
* 安装并配置好 Docker CE
* 创建两个账户：root 和 非 root 用户（下面的例子中是 `mcalizo`）。


如果你需要在你的 RHEL 8/CentOS 8 服务器上设置 Docker，你可以按照这些 [说明](https://www.linuxtechi.com/install-docker-ce-centos-8-rhel-8/)。如果你运行的是 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 选项](https://docs.docker.com/storage/volumes/) 将 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 上下文](https://docs.docker.com/engine/reference/commandline/context/)：



```
[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 在默认情况下是 **不启用** 的。 这就是问题所在！要解决这个问题，按 [文档](https://docs.docker.com/engine/reference/commandline/dockerd/) 说明，通过更新或创建文件 `/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 发行版](https://www.redhat.com/en/topics/linux/whats-the-best-linux-distro-for-you) 中。为了借助它保护你的系统不被破坏，请确保 SELinux 保持开启状态。


如果你想了解更多，请参阅：


* [如何在 CentOS 8 / RH 上安装 Docker CE](https://www.linuxtechi.com/install-docker-ce-centos-8-rhel-8/)
* [Docker 安全速查表](https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html)
* [dockerd 文档](https://docs.docker.com/engine/reference/commandline/dockerd/)
* [卷的使用文档](https://docs.docker.com/storage/volumes/)
* [什么是 SELinux？](https://www.redhat.com/en/topics/linux/what-is-selinux)




---


via: <https://opensource.com/article/20/11/selinux-containers>


作者：[Mike Calizo](https://opensource.com/users/mcalizo) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
When things aren't working correctly in your Linux environment, the easiest thing to do is disable Security-Enhanced Linux ([SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux)). Things suddenly begin to work, and you forget about it—but this is a common pitfall that means you've lost a very powerful security tool.

Threats are rising alongside the rise of containers, microservices, and distributed architecture. This is due to an old, well-known issue: velocity. The advantage of containers is that they enable you to move fast, do more, and change quickly. This means container adoption has gone off the roof, but the speed it affords also means you will encounter more issues and vulnerabilities. This happens naturally when you're doing more things faster and quicker.

## How to mitigate threats


As Sun Tzu said, "The wise warrior avoids the battle." This quote really resonates when it comes to containers' basic defense. To avoid problems (battles), make sure that your container host is secure and that you can use SELinux as your first line of defense.

SELinux is an open source project released in 2000 and integrated into the Linux kernel in 2003. According to [Red Hat's explainer](https://www.redhat.com/en/topics/linux/what-is-selinux), "SELinux is a security architecture for [Linux systems](https://www.redhat.com/en/topics/linux/what-is-linux) that allows administrators to have more control over who can access the system. It was originally developed by the United States National Security Agency (NSA) as a series of patches to the [Linux kernel](https://www.redhat.com/en/topics/linux/what-is-the-linux-kernel) using Linux Security Modules (LSM)."

## Get started

When you think about containers, the first thing that probably comes into mind is [Docker](https://opensource.com/resources/what-docker). Docker started a container adoption revolution after it emerged in 2013. It is one of the main reasons that containers exploded in popularity, but as mentioned above, the high level of adoption increased users' vulnerability to security risks.

Before you can secure your Docker containers with SELinux, you need to set some things up.

### Prerequisites:

- CentOS 8/RHEL 8 installed and configured
- Docker CE installed and configured
- Two accounts created: root and non-root (
`mcalizo`

in the examples below)

If you need to set up Docker on your RHEL 8/CentOS 8 server, you can follow these [instructions](https://www.linuxtechi.com/install-docker-ce-centos-8-rhel-8/). If you're running RHEL 8, you need to remove the pre-installed Podman and runc packages before beginning.

First, make sure SELinux is enabled:

```
[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 ~]$
```


Then, verify your OS version and that Docker is running. Log in as root and run:

```
[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
```


Check your Docker version:

```
[root@rhel82 ~]# docker --version
Docker version 19.03.13, build 4484c46d9d
```


## Hack your host

One of the best ways to understand a problem is to experience it. So, I'll show you how easy it is to inject malicious code into a Docker host if your security is not set up properly.

To be able to do something bad on the Docker host, the malicious non-root user (`mcalizo`

in this tutorial) must be part of the group that can instantiate Docker containers.

First, confirm what group the `mcalizo`

user belongs to:

```
[root@Rhel82 ~]# groups mcalizo
mcalizo : mcalizo
```


The output shows that `mcalizo`

belongs only to its own group. This means `mcalizo`

can't instantiate Docker containers and will get this error if it tries:

```
[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'.
```


To allow `mcalizo`

to instantiate the container, add the user to the `docker`

group:

```
[root@Rhel82 ~]# usermod -G docker -a mcalizo
[root@Rhel82 ~]# groups mcalizo
mcalizo : mcalizo docker
```


Next, deploy a `fedora:latest`

container and log into the instantiated container to explore it:

```
[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)
```


While you're logged into the newly created container, you can see you are automatically logged in as root:

```
sh-5.0# whoami
root
sh-5.0#
```


As `root`

user, you can do anything in this container, which means you can exploit the container host and do a lot of damage. Because you can instantiate a container, you can do things to the host even if you are not part of the host's sudoers account.

Exit the container you just created, and create a new container to demonstrate the exploit:

```
[mcalizo@Rhel82 ~]$ docker run -it --rm -v /:/exploit fedora:latest /bin/bash
[root@131043f2e306 /]#
```


The [-v option](https://docs.docker.com/storage/volumes/) mounts the Docker host's `/`

directory to the container under the `/exploit`

directory:

```
[root@131043f2e306 /]#ls exploit/
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
```


Because it is mounted, you can do *anything* on the Docker host. For example, you can delete files, edit specific configurations to harm the system, or even install a Trojan horse application or other malware to steal important information.

## Why does this happen?

You may be wondering why this is possible since SELinux is in enforcing mode. Dig deeper into SELinux to see where things went wrong.

Verify that SELinux has a [Docker context](https://docs.docker.com/engine/reference/commandline/context/):

```
[mcalizo@Rhel82 ~]$ ps -eZ | grep docker
system_u:system_r:container_runtime_t:s0 30768 ? 00:00:04 dockerd
[mcalizo@Rhel82 ~]$
```


As expected, it does. This means SELinux manages the Docker daemon. Inspect the Docker daemon to see if SELinux is enabled by default:

```
[mcalizo@Rhel82 ~]$ docker info | grep Security -A3
Security Options:
seccomp
Profile: default
Kernel Version: 4.18.0-193.el8.x86_64
```


SELinux is *not* enabled by default. This is the problem! To fix it, enable SELinux to control and manage Docker by updating or creating the file `/etc/docker/daemon.json`

as [documented here](https://docs.docker.com/engine/reference/commandline/dockerd/) (you must have root access to do this):

```
[root@Rhel82 ~]# cat /etc/docker/daemon.json
{
"selinux-enabled": true
}
[root@Rhel82 ~]#
[root@Rhel82 ~]# systemctl restart docker
```


After creating or updating the file and restarting Docker, you should see that SELinux support is enabled in the Docker daemon:

```
[root@Rhel82 ~]# systemctl restart docker
[mcalizo@Rhel82 root]$ docker info | grep Security -A3
Security Options:
seccomp
Profile: default
selinux
[mcalizo@Rhel82 root]$
```


While it's still possible to mount a specific filesystem in your Docker host on your Docker container, updating or accessing the file is no longer allowed:

```
[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 /]#
```


## Learn more

Your first line of defense in the container world depends on how strongly you set up your container hosts' operating system. There are numerous ways to implement Linux security, including options available on the market to augment your security posture.

SELinux is an additional layer of security that is built into [Linux distributions](https://www.redhat.com/en/topics/linux/whats-the-best-linux-distro-for-you) by default. To take advantage of it and protect your system against compromise, make sure SELinux remains on.

If you want to learn more, see:

## Comments are closed.