Docker镜像安全扫描
@ wgjak47 | 星期一,十二月 24 日,2018 年 | 4 分钟阅读 | 更新于 星期一,十二月 24 日,2018 年

使用clair对Docker image进行安全扫描

Docker镜像并不安全

随着微服务兴起,Docker成为一种越来越流行的部熟方式,但是docker的容器是基于docker镜像构建的,如果Docker镜像本身存在安全漏洞,那么这个容器显然是不安全的。Docker兴起之后,原本部署环境的构建的任务有一部分落在的开发人员的身上,而相比与传统物理机/虚拟机部署有专门的SRE/SA对环境进行维护,开发人员可能会忽视相关软件的安全漏洞。

Docker镜像扫描工具

针对Docker镜像有多种安全审计工具可用,我这里试用了CoreOS的Clair,其它的可参考最下面的引用。 ** 注意下面的部署方式只是本机测试,不适合作为生产环境的部署方式 **

Clair服务端安装配置

docker-compose文件

# 下载Compose文件
curl -L https://raw.githubusercontent.com/coreos/clair/master/contrib/compose/docker-compose.yml -o $HOME/docker-compose.yml

这里注意下载下来的文件默认使用的是git版的,这个不太稳定,建议修改image为quay.io/coreos/clair

Clair配置文件

curl -L https://raw.githubusercontent.com/coreos/clair/master/config.yaml.sample -o $HOME/clair_config/config.yaml

这里按照官方文档修改一下数据库的配置,更改host为postgresql,增加password变量,值为password

配置代理

Clair需要连接Debian Security Tracker的API, 而国内环境没有镜像,如果出现下载失败的问题,可以使用代理服务器进行访问,这里因为条件限制,我使用shadowsocks配合polipo生成https代理,可以根据需求使用其它方式:

  • 配置shadowsocks 配置文件略
# 启动socks5代理
ss-local -c /etc/shadowsocks/config.json
  • 配置polipo
sudo emerge -av polipo # gentoo
sudo apt-get install polipo # Debian/ubuntu

启动https/http代理

polipo socksParentProxy=localhost:1080 proxyAddress=0.0.0.0

或者修改/etc/polipo/config,注意修改三个选项

socksParentProxy=localhost:1080 # socks5 proxy地址
proxyAddress=0.0.0.0 # 监听地址,这里选择0.0.0.0是为了本地的Docker容器访问方便
#allowedClients=127.0.0.1 # 这个可以注释掉,或者添加相关IP到白名单
  • 配置compose文件 增加enviroment变量:
environment:
https_proxy: http://10.249.41.131:8123 # 这里是Docker宿主机的IP

compose/config文件样例

  • compose文件
version: '2'
services:
postgres:
container_name: clair_postgres
image: postgres:latest
restart: unless-stopped
environment:
POSTGRES_PASSWORD: password

clair:
container_name: clair_clair
image: quay.io/coreos/clair:v2.0.7
environment:
https_proxy: http://10.249.41.131:8123
restart: unless-stopped
depends_on:
- postgres
ports:
- "6060-6061:6060-6061"
links:
- postgres
volumes:
- /tmp:/tmp
- ./clair_config:/config
command: [-config, /config/config.yaml]
  • config 文件
# Copyright 2015 clair authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# The values specified here are the default values that Clair uses if no configuration file is specified or if the keys are not defined.
clair:
database:
# Database driver
type: pgsql
options:
# PostgreSQL Connection string
# https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
source: host=postgres port=5432 user=postgres sslmode=disable statement_timeout=60000 password=password

# Number of elements kept in the cache
# Values unlikely to change (e.g. namespaces) are cached in order to save prevent needless roundtrips to the database.
cachesize: 16384

# 32-bit URL-safe base64 key used to encrypt pagination tokens
# If one is not provided, it will be generated.
# Multiple clair instances in the same cluster need the same value.
paginationkey:

api:
# v3 grpc/RESTful API server address
addr: "0.0.0.0:6060"

# Health server address
# This is an unencrypted endpoint useful for load balancers to check to healthiness of the clair server.
healthaddr: "0.0.0.0:6061"

# Deadline before an API request will respond with a 503
timeout: 900s

# Optional PKI configuration
# If you want to easily generate client certificates and CAs, try the following projects:
# https://github.com/coreos/etcd-ca
# https://github.com/cloudflare/cfssl
servername:
cafile:
keyfile:
certfile:

updater:
# Frequency the database will be updated with vulnerabilities from the default data sources
# The value 0 disables the updater entirely.
interval: 2h
enabledupdaters:
- debian
- ubuntu
- rhel
- oracle
- alpine

notifier:
# Number of attempts before the notification is marked as failed to be sent
attempts: 3

# Duration before a failed notification is retried
renotifyinterval: 2h

http:
# Optional endpoint that will receive notifications via POST requests
endpoint:

# Optional PKI configuration
# If you want to easily generate client certificates and CAs, try the following projects:
# https://github.com/cloudflare/cfssl
# https://github.com/coreos/etcd-ca
servername:
cafile:
keyfile:
certfile:

# Optional HTTP Proxy: must be a valid URL (including the scheme).
proxy:

启动

docker-compose up -d postgres # 官方的compose文件有的时候会让postgres后启动,导致clair服务启动失败
docker-compose up -d

Clair客户端安装配置

Clair有多种客户端,参见:integrations这里我使用支持Python3的Paclair。

安装

pip install paclair # 注意是Python3

配置文件

General:
clair_url: 'https://localhost:6060'
verify: "/etc/ssl/certs/my_custom_ca.crt"
Plugins:
Docker:
class: paclair.plugins.docker_plugin.DockerPlugin
registries:
registry.gitlab.domain.com:
auth:
- "username"
- "password"
verify: "/etc/ssl/certs/ca-certificates.crt"

使用paclair检测镜像软件漏洞

clair检测需要两步: 第一步,将image提交到clair服务端

paclair --conf client.yml Docker msyql:5.7 push

第二步,访问clair服务端API,得到分析结果

paclair --conf client.yml Docker mysql:5.7 analyse # 默认的Json格式输出
paclair --conf client.yml Docker mysql:5.7 analyse --output-format html --output-dir /tmp  --output-report file # 以html格式输出到/tmp下与image同名的文件

Debian 7 is OUT Of DATE!!!

由于Debian 7已经停止支持,所以如果你扫描基于Debian 7的镜像,会发现一个漏洞也没有,这并不是说Debian 7非常安全,反而是因为Debian Security tracker没有Debian 7的数据了,所以Debian 7的安全问题非常严重。所以尽量不要使用Debian 7的镜像构建对外服务,其它发行版同理。

分析结果

请在这里输入图片描述

分析结果中混杂了许多关于kernel的漏洞,而Docker使用的是宿主机的kernel,因此这些漏洞是不重要的,另外有些软件,对外的服务并没有直接/间接使用,因此也可以选择忽略。建议找安全相关的同事咨询或者自己自己查看漏洞说明Orz。

参考

Docker安全入门与实战 clair github repo paclair github repo