其实我们所使用的所有计算设备和程序都并非是绝对安全的,就比如现在比较流行的Docker,其实在某些层面也是存在一定隐患的,今儿就谈谈容器最基础的安全问题。

1、镜像问题

   容器的镜像大多数会来源于互联网公共仓库,非常方便,下载回来即可使用。而这部分来源的镜像又有谁做过安全扫描和安全检查?镜像中会不会存在严重的系统漏洞?这都是未知数,而且有没有恶意的人做了手脚我们也无法得知。所以大多数情况下我们更应该定制自己的base images(基础镜像),尽可能的精简,能不要的都不要。

参考:

https://raw.githubusercontent.com/docker/docker/master/contrib/mkimage-yum.sh

如果你使用了一个来路不明的镜像,那么下面的实例有可能会是你的下场,即使不是这种入侵方式,如果在镜像内嵌入了一个反链接程序(为什么是反链接?因为大多数企业的防火墙都是对外部访问内部有无数的过滤规则,而内部出去却宽松的很),只要启动容器就会连接到外面的某个IP,然后窃取数据。总之会有N多的方式等着你中招,所以镜像的构建是最最最基础的一个环节。

2、容器内敏感的启动用户

容器镜像无论是下载的还是自建的,都会面临同样一个问题,就是启动容器内进程的用户往往都是root,至少目前我在大多数生产环境中看到的还是这样(应用程序往容器里一丢,管你用什么账户启动,但是默认都是root啊!),其实这个道理就和物理机或者虚拟机上启动进程的用户是同一个道理。

如果应用程序存在漏洞可以被溢出攻击或者其他方式利用,那么获得的权限就是root权限,这个在容器内也是一样的,一个简单的实验,证明这个问题:

root启动的容器内进程:(演示漏洞CVE-2017-538 

浅谈容器安全之镜像和启动用户_java

通过远程调用,我获得到容器内的ps 进程,并且启动者是root

当前id显示的用户也是root,充分说明漏洞是和进程的启动账户有关系。

然后,试试删除功能,指令已经执行。

 

再次读取的时候已经无法找到文件了,如果这是其他文件呢?是共享卷的日志呢,又或者是数据卷呢?

 

nobody启动的容器内进程

进程是nobody账户启动的。 

浅谈容器安全之镜像和启动用户_java_02

然后确认id用户,是nobody账户。

浅谈容器安全之镜像和启动用户_java_03

测试删除,没有成功。

 

实验到这里已经充分说明,容器内的启动账户依然是我们需要注意的高危事项,其实如果能调用到这一步,破坏力可想而知,比如挂掉你的容器,删除你共享卷数据,如果你又恰巧集成了安装源,vimgcc什么的,那就全乎了。有人说破坏是在容器内,对其他的影响不大?其实在我们不知道的或者没有涉足的技术里,一个容器内的root,为什么这么确定他无法逾越namespace呢?

更多入侵者进来不是为了破坏,而是为了数据窃取,你能给他的权限越小,工具越少,那么对方的难度就会越大,所以尽可能的使用普通账户启动容器内进程,尽可能的自己构建基础镜像,将基础镜像精简到最小。