欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

偷偷学 Docker 系列 | 细谈 Docker存在的安全问题 | 架构缺陷与安全机制 | 衡量安全基线的六大标准

程序员文章站 2024-03-19 14:31:52
...

前言:Docker 容器与虚拟机的区别

①隔离性(共享)

  • 虚拟机通过添加 Hypervisor 层,即虚拟化监控平台,通过这个层面虚拟出网卡、内存、CPU 等虚拟硬件,这些虚拟硬件是靠一个个线程来管理的
  • 再在其上建立虚拟机,每个虚拟机都相当于一个进程,有自己的系统内核,是一个独立的系统,从系统的层面上进行隔离 ,遇到问题也不会影响到其他的虚拟机乃至宿主机,安全性有很好的保障
  • 而 Docker 容器则是通过隔离的方式,将文件系统、进程、设备、网络等资源进行隔离,再对权限、CPU 资源等进行控制,最终让容器之间互不影响(Cgrep:CPU、内存、IO)
  • 容器与宿主机共享内核、文件系统、硬件等资源,可能会因此造成安全隐患,导致容器影响到宿主机

②性能(损耗)

  • 与虚拟机相比,容器资源损耗要少,在同样的宿主机下,能够建立容器的数量要比虚拟机多
  • 但是,虚拟机的安全性要比容器好,要从虚拟机攻破到宿主机或其他虚拟机,需要先攻破 Hypervisor 层,这是极其困难的
  • 而且,docker 容器与宿主机共享内核、文件系统等资源,相互之间可能对其他容器、宿主机产生一定的影响

一、细谈 Dcoker 存在的安全问题

1.自身漏洞方面

  • 作为一款开源应用,Docker 本身在实现上会有一些代码缺陷,官方统计 Docker 在历史版本中,到目前为止有超过 20 项漏洞
  • 黑客能够利用这些漏洞,通过这些入口以来实现权限的提升、盗取信息等,这给 Docker 自身带了安全隐患,也因此 Docker 版本更迭非常快,Docker 用户最好将 Docker 升级为 最新版本

2.源码问题方面

①黑客上传恶意镜像

  • Docker 提供了 Docker hub 官方公有仓库,可以让用户上传创建的镜像,以便用户的下载,快速搭建环境,但同时也带来了一些安全问题

  • 如果有黑客在制作的镜像中植入木马、后门等恶意软件,一旦别的用户下载了这个镜像并加载成了容器,那么环境从一开始就不安全,可能会留出一个后门并暴露出一个端口

  • 后续更没有什么安全可言,这样会方便黑客直接从后门进入干坏事,不过也没有这么容易,用户上传的镜像会首先放在官方的一个非安全区域,该平台会将其运行测试,确认无误后才会放至安全区域以供广大用户下载使用

②镜像使用有漏洞的软件

  • 假设这样一个场景,你下载了一个镜像,但是里面 nginx 的版本较旧,而老版本意味着存在安全性漏洞,一般人只会觉得能运行起来就没问题了,但是你有没有想过为什么我们之前部署 nginx 时为什么要隐藏版本号?
  • 所以下载镜像后,需要检查里面软件的版本信息,对应的版本是否存在漏洞,并及时更新打上补丁

③中间人攻击(篡改)

  • 镜像在传输过程中可能被拦截(篡改),比如 ARP 欺骗攻击
  • 目前新版本的 Docker 已经提供了相应的校验机制来预防这个问题(Hash 算法验证)

二、细谈 Docker 的架构缺陷与安全机制

Docker 本身的架构与机制就可能产生问题,例如这样一种攻击场景,黑客已经控制了宿主机上的一些容器,或者获得了通过在公有云上建立容器的方式,然后对宿主机或其他容器发起攻击

1.容器之间的局域网攻击

  • 主机上的容器之间可以构成局域网,因此针对局域网的 ARP 欺骗、嗅探、广播风暴等攻击方式都可以用上
  • 所以,在一个主机上部署多个容器需要合理的配置网络,做防火墙策略,设置 iptable 规则

2.DDoS 攻击耗尽资源

  • 利用很多“肉鸡”主机在关键时刻统一向目标发送大量请求,但不使用功能, 也就是占着茅坑不拉屎,严重影响目标的服务正常运行

  • Cgroups 安全机制就是要防止此类攻击的,不要为单一的容器分配过多的资源即可避免此类问题

3.利用宿主机漏洞

  • Docker 与虚拟机的一个重要的区别就是 Docker 与宿主机共用一个操作系统内核,所以,一旦宿主机存在漏洞,那么容器也就不安全了
  • 反过来看,在容器被入侵时,攻击者还可以利用内核漏洞跳到宿主机做更多的事情

4.用户权限

  • Docker 进入容器时会自动进行降权处理,保证安全性,但是如果以 root 用户权限运行容器,容器内的 root 用户也就拥有了宿主机的 root 权限
  • 那么其中的资源就得不到安全性的保障,这种“共享” root 权限的做法会导致安全隐患

三、细谈 Docker 衡量安全基线的六大标准

1.内核级别

  1. 及时更新内核
  2. User NameSpace(容器内的 root 权限在容器之外处于非高权限状态)
  3. Cgroups(对资源的配额和度量)
  4. SELiux/AppArmor/GRSEC(控制文件访问权限)
  5. Capability(权限划分)
  6. Seccomp(限定系统调用)
  7. 禁止将容器的命名空间与宿主机进程命名空间共享(如果容器被攻陷,该进程/系统服务最严重会直接被宕掉)

2.主机级别

  1. 为容器创建独立分区
  2. 仅运行必要的服务(尽量别开 FTP 服务,因为若不禁锢家目录,FTP 就可以查看任意文件)
  3. 禁止将宿主机上敏感目录映射到容器(相当于挂载,若该目录被误操作删除,可能会导致严重后果)
  4. 对 Docker 守护进程、相关文件和目录进行审计(查询日志文件)
  5. 设置适当的默认文件描述符数:内核(kernel)利用文件描述符来访问文件,文件描述符是非负整数,打开现存文件或新建文件时,内核会返回一个文件描述符,且读写文件也需要使用文件描述符来指定待读写的文件
  6. 用户权限为 root 的 Docker 相关文件的访问权限应该为 644 或者更低权限
  7. 周期性检查每个主机的容器清单,并清理不必要的容器

3.网络级别

  1. 通过 iptables 设定规则,实现禁止或允许容器之间网络流量
  2. 允许 Docker 修改 iptables
  3. 禁止将 Docker 绑定到其他 IP/Port 或者 Unix Socket(通信文件,会影响其他服务通信)
  4. 禁止在容器上映射特权端口(比如80,最好别用默认端口号,不安全)
  5. 容器上只开放所需要的端口
  6. 禁止在容器上使用仅主机网络模式(该模式相当于局域网,容易被局域网条件性攻击)
  7. 若宿主机有多个网卡,将容器进入流量绑定到特定的主机网卡上(这样就只用对特定区域做规则即可)

4.镜像级别

  1. 创建本地镜像仓库服务器(Harbor,仓库安全性)
  2. 镜像中软件都为最新版本(镜像安全性)
  3. 使用可信任的镜像文件(星级),并通过安全通道下载
  4. 重新构建镜像而非对容器和镜像打补丁
  5. 合理管理镜像标签,及时移除不再使用的镜像
  6. 使用镜像扫描与镜像签名(往往用于共有仓库,是一种验证机制)

5.容器级别

  1. 容器最小化,操作系统镜像最小级别
  2. 容器以单一主进程的方式运行
  3. 禁止 privileged 标记使用特权容器(即不做降权处理)
  4. 禁止在容器上运行 ssh 服务(最好用 exec)
  5. 以只读的方式挂载容器的根目录系统(不要以读写的方式)
  6. 明确定义属于容器的数据盘符(放至不同的盘符中)
  7. 通过设置 on-failure 限制容器尝试重启的次数(默认六次),容器反复重启容易丢失数据
  8. 限制在容器中可用的进程树,以防止 fork bomb(fork 进程炸弹,会迅速增长子进程,耗尽系统进程数量)

6.其他设置

  1. 定期对宿主机系统及容器进行安全审计
  2. 使用最少资源和最低权限运行容器
  3. 避免在同一宿主机上部署大量容器,维持在一个能够管理的数量(服务器核心数为48核心数,容器数量控制到80~100,每个核心数权重30%,适用于生产环境)
  4. 监控 Docker 容器的使用,性能以及其他各项指标(Zabbix 或普罗米修斯)
  5. 增加实时威胁检测和事件响应功能
  6. 使用中心和远程日志收集服务(ELK/EFK)

五、其他注意事项

1.Docker remote api 访问控制

'docker 的远程调用 API 接口存在未授权访问漏洞,至少应限制外网访问'
'建议使用 Socket 方式访问'
'监听内网 ip,docker daemon 启动方式如下:'

[[email protected] ~]# vim /usr/lib/systemd/system/docker.service
'//开放本地监听地址和端口,最好注释之前的ExecStart,另开新的一行'
[[email protected] ~]# ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://192.168.126.16:2375


[[email protected] ~]# systemctl daemon-reload		'//重新加载服务配置文件'
[[email protected] ~]# systemctl restart docker

[[email protected] ~]# netstat -natp|grep 2375
tcp        0      0 192.168.126.16:2375     0.0.0.0:*               LISTEN      106593/dockerd      


'//然后,在宿主机的firewalld上做IP访问控制即可(source address是客户端地址)'
[[email protected] ~]# firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.195.128" port protocol="tcp" port="2375" accept"
'//--permanent:持久化设定,永久修改;--add-rich-rule:添加规则,ipv4地址/客户端地址/协议'
[[email protected] ~]# firewall-cmd --reload
'//重新加载防火墙配置'

'//客户端操作实现远程调用'
[[email protected] ~]#docker -H tcp://192.168.126.16 images

2.限制流量流向

'使用防火墙过滤器限制Docker容器的源IP地址范围与外界通讯'
'即外面可以访问里面,但是里面不能任意访问外面,增强安全性'

firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.126.0/24" reject"

大量安全隐患问题的出现是因为 Docker 容器端口向外暴露所引起的漏洞,除了操作系统账户权限控制上的问题,更在于对 Docker Daemon 的进程管理上存在隐患

建议:

  1. 不在有外网 ip 的机器上使用 Docker 服务

  2. 使用 K8s 等 docker 编排系统管理 Docker 容器

  3. 宿主机上 Docker daemon (守护进程)启动命令加一个 “–iptables=false”,然后把常用 iptables 写进文件里,再用 iptables-restore 去刷新,这样 iptables 规则会直接在 docker 的守护进程上就能生效了

3.镜像安全

  • Docker 镜像安全扫描,在镜像仓库客户端使用证书认证,对下载的镜像进行检查,通过与 CVE 数据库同步扫描镜像,一旦发现漏洞则通知用户处理,或者直接阻止镜像继续构建(这是官网干的活,我们基本不用关注)

  • 如果公司使用的是自己的镜像源,可以跳过此步;否则,至少需要验证 baseimage 的 md5 等特征值,确认一致没有被中间人篡改,之后再基于 baseimage 进一步构建

  • 一般情况下,要确保只从受信任的库中获取镜像,不建议使用 registry,毕竟只是一个容器,相对而言不安全,推荐使用 harbor 私有仓库,有身份验证的凭据,更加安全