item
|
descript
|
容器最小化
|
仅在容器中运行必要的服务,像ssh等服务是绝对不能开启的。使用以下方式来管理你的容器:
docker exec -it mycontainer bash
|
Docker remote api访问控制
|
Docker的远程调用API接口存在未授权访问漏洞,至少应限制外网访问。如果可以,建议还是使用socket方式访问。 建议监听内网ip或者localhost,docker daemon启动方式:
docker -d -H uninx:///var/run/docker.sock -H tcp://10.10.10.10:2375
#或者在docker默认配置文件指定
other_args=" -H unix:///var/run/docker.sock -H tcp://10.10.10.10:2375"
然后在宿主iptables上做访问控制
*filter:
HOST_ALLOW1 - [0:0]
-A HOST_ALLOW1 -s 10.10.10.1/32 -j ACCEPT
-A HOST_ALLOW1 -j DROP
-A INPUT -p tcp -m tcp -d 10.10.10.10 --port 2375 -j HOST_ALLOW1
|
限制流量流向
|
可以使用以下iptables过滤器[7]限制Docker容器的源IP地址范围与外界通讯。
iptables -A FORWARD -s -j REJECT --reject-with icmp-admin-prohibited
Iptables -A FORWARD -i docker0 -o eth0 -j DROP-A FORWARD -i docker0 -o eth0 -m state –state ESTABLISHED -j ACCEPT
我们处理过大量因为Docker容器端口外放引起的漏洞,除了操作系统账户权限控制上的问题,更在于对Docker Daemon的进程管理上存在隐患。我们都知道,目前常用的Docker版本都支持Docker Daemon管理宿主iptables的,而且一旦启动进程加上-p host_port:guest_port的端口映射,Docker Daemon会直接增加对应的FORWARD Chain并且-j ACCEPT,而默认的DROP规则是在INPUT链做的,对docker没法限制,这就留下了很严重的安全隐患了。因此建议: 1. 不在有外网ip的机器上使用Docker服务 2. 使用k8s等docker编排系统管理Docker容器 3. 宿主上Docker daemon启动命令加一个--iptables=false,然后把常用iptables写进文件里,再用iptables-restore去刷。
|
使用普通用户启动Docker服务
|
截至Docker 1.10用户命名空间由docker守护程序直接支持。此功能允许容器中的root用户映射到容器外部的非uid-0用户,这可以帮助减轻容器中断的风险。此功能可用,但默认情况下不启用。 1.使用用户映射 要解决特定容器中的用户0在宿主系统上等于root的问题,LXC允许您重新映射用户和组ID。配置文件条目如下所示:
lxc.id_map = u 0 100000 65536
lxc.id_map = g 0 100000 65536
这将容器中的前65536个用户和组ID映射到主机上的100000-165536。主机上的相关文件是/etc/subuid和/etc/subgid。此映射技术命名为从属ID,因此称为“子”前缀。 对于Docker,这意味着将其作为-lxc-conf参数添加到docker run:
docker run -lxc-conf ="lxc.id_map = u 0 100000 65536" -lxc-conf ="lxc.id_map = g 0 100000 65536"
2.启动容器时不带--privileged参数
docker run -it debian8:standard /bin/bash
|
文件系统限制
|
挂载的容器根目录绝对只读,而且不同容器对应的文件目录权限分离,最好是每个容器在宿主上有自己单独分区。
su con1
docker run -v dev:/home/mc_server/con1 -it debian8:standard /bin/bash
su con2
docker run -v dev:/home/mc_server/con2 -it debian8:standard /bin/bash
|
镜像安全
|
如下图所示,在镜像仓库客户端使用证书认证,对下载的镜像进行检查 ,通过与CVE数据库同步扫描镜像,一旦发现漏洞则通知用户处理,或者直接阻止镜像继续构建。 如果使用的是公司自己的镜像源,可以跳过此步;否则至少需要验证baseimage的md5等特征值,确认一致后再基于baseimage进一步构建。 一般情况下,我们要确保只从受信任的库中获取镜像,并且不要使用--insecure-registry=[]参数。具体实现我们在漏洞扫描部分一块介绍。
|
Docker client端与 Docker Daemon的通信安全
|
按照Docker官方的说法,为了放置链路劫持、会话劫持等问题导致docker通信时被中间人攻击,c/s两端应该通过加密方式通讯。
docker –tlsverify –tlscacert=ca.pem –tlscert=server-cert.pem –tlskey=server-key.pem -H=0.0.0.0:2376
|
资源限制
|
限制容器资源使用,最好支持动态扩容,这样既可以尽可能降低安全风险,也不影响业务。下面是使用样例,限制cpu使用第2核、分配2048
docker run -tid –name ec2 –cpuset-cpus 3 –cpu-shares 2048 -memory 2048m –rm –blkio-weight 100 --pids--limit 512
更多限制可以参考Docker官方说明:
--cpu-period Limit CPU CFS (Completely Fair Scheduler) period
--cpu-quota Limit CPU CFS (Completely Fair Scheduler) quota
--device-read-bps=[] Limit read rate (bytes per second) from a device
--device-read-iops=[] Limit read rate (IO per second) from a device
--device-write-bps=[] Limit write rate (bytes per second) to a device
--device-write-iops=[] Limit write rate (IO per second) to a device
--kernel-memory Kernel memory limit
--label-file=[] Read in a line delimited file of labels
-m, --memory Memory limit
--memory-reservation Memory soft limit
--memory-swap Swap limit equal to memory plus swap: '-1' to enable unlimited swap
--pids-limit Tune container pids limit (set -1 for unlimited)
--ulimit=[] Ulimit options
|
宿主及时升级内核漏洞
|
使用Docker容器对外提供服务时,还要考虑宿主故障或者需要升级内核的问题。这时为了不影响在线业务,Docker容器应该支持热迁移,这个可以纳入容器调度系统的功能设计中。此外,还应考虑后续的内核升级方案规划、执行以及回迁方案等。
|
避免docker容器中信息泄露
|
就像之前github上大量泄露个人或企业各种账号密码的问题,我们一般使用dockerfile或者docker-compose文件创建容器,如果这些文件中存在账号密码等认证信息,一旦docker容器对外开放,则这些宿主机上的敏感信息也会随之泄露。因此可以通过以下方式检查容器创建模板的内容:
# check created users
grep authorized_keys $dockerfile
# check OS users
grep "etc/group" $dockerfile
# Check sudo users
grep "etc/sudoers.d" $dockerfile
# Check ssh key pair
grep ".ssh/.*id_rsa" $dockerfile
# Add your checks in below
|
安装安全加固
|
如果可能,使用安全的Linux内核、内核补丁。如SELinux,AppArmor,GRSEC等,都是Docker官方推荐安装的安全加固组件。 如果先前已经安装并配置过SELinux,那么可以在容器使用setenforce 1来启用它。Docker守护进程的SELinux功能默认是禁用的,需要使用--selinux-enabled来启用。容器的标签限制可使用新增的—-security-opt加载SELinux或者AppArmor的策略进行配置,该功能在Docker版本1.3[9]引入。例如:
docker run --security-opt=secdriver:name:value -i -t centos bash
SELinux的相关选项:
--security-opt ="label:user:USER"(设置标签用户)
--security-opt ="label:role:ROLE"(设置标签角色)
--security-opt ="label:type:TYPE"(设置标签类型)
--security-opt ="label:level:LEVEL"(设置标签级别)
--security-opt ="label:disable"(完全禁用标签限制)
AppArmor的选项:
--secutity-opt ="apparmor:PROFILE"(设置AppArmor配置文件)
GRSEC的选项:
gradm -F -L /etc/grsec/learning.logs
GRSEC的更多说明请参考:
https://en.wikibooks.org/wiki/Grsecurity
|
限制系统命令调用
|
1.系统调用层面: Linux系统调用列表见:
http://www.ibm.com/developerworks/cn/linux/kernel/syscall/part1/appendix.html
Seccomp(secure computing mode),就是安全计算模式,这个模式可以设置容器在对系统进行调用时进行一些筛选,也就是所谓的白名单。它可以去指定允许容器使用哪些的调用,禁止容器使用哪些调用,这样就可以增强隔离,它其实也是访问控制的一个部分。 2.函数调用层面 通过使用“–security-optseccomp=”标记来指定自定义的 seccomp 描述文件:
$ docker run -d –security-opt seccomp:allow:clock_adjtime ntpd
这条命令将会允许容器内使用 clock_adjtime 调用
$docker run -d –security-opt seccomp:deny:getcwd /bin/sh
这条命令将会禁止容器内执行的 shell 查询当前自己所在的目录
--security-opt=[]
Security Options
"label=user:USER" : Set the label user for the container
"label=role:ROLE" : Set the label role for the container
"label=type:TYPE" : Set the label type for the container
"label=level:LEVEL" : Set the label level for the container
"label=disable" : Turn off label confinement for the container
"no-new-privileges" : Disable container processes from gaining additional privileges
"seccomp=unconfined" : Turn off seccomp confinement for the container
"seccomp=profile.json : White listed syscalls seccomp Json file to be used as a seccomp filter
"apparmor=unconfined" : Turn off apparmor confinement for the container
"apparmor=your-profile" : Set the apparmor confinement profile for the container
在没有缺省secconf配置文件的情况下运行,可以通过unconfined运行配置不在默认seccomp配置文件的容器。
$ docker run --rm -it --security-opt seccomp =ulimit-debian:jessie \ unshare --map-root-user --user sh -c whoami
|
suid和guid限制
|
SUID和GUID程序在受攻击导致任意代码执行(如缓冲区溢出)时将非常危险,因为它们将运行在进程文件所有者或组的上下文中。如果可能的话,使用特定的命令行参数减少赋予容器的能力,阻止SUID和SGID生效。
docker run -it --rm --cap-drop SETUID --cap-drop SETGID
还有种做法,可以考虑在挂载文件系统时使用nosuid属性来移除掉SUID能力。最后一种做法是,删除系统中不需要的SUID和GUID程序。这类程序可在Linux系统中运行以下命令而找到:
find / -perm -4000 -exec ls -l {} \; 2>/dev/null
find / -perm -2000 -exec ls -l {} \; 2>/dev/null
然后,可以使用类似于下面的命令将移除SUID和GUID文件权限:
sudo chmod u-s filename sudo chmod -R g-s directory
|
能力限制
|
尽可能降低Linux能力。 Docker默认的能力包括:chown、dac_override、fowner、kill、setgid、setuid、setpcap、net_bind_service、net_raw、sys_chroot、mknod、setfcap、和audit_write。在命令行启动容器时,可以通过--cap-add=[]或--cap-drop=[]进行控制。例如:
docker run --cap-drop setuid --cap-drop setgid -ti /bin/sh
此功能在Docker 1.2版本引入。
|
多租户环境
|
由于Docker容器内核的共享性质,无法在多租户环境中安全地实现责任分离。建议将容器运行在没有其它目的,且不用于敏感操作的宿主上。可以考虑将所有服务迁移到Docker控制的容器城。可能的话,设置守护进程使用--icc=false,并根据需要在docker run时指定-link,或通过—-export=port暴露容器的一个端口,而不需要在宿主上发布。将相互信任的容器的组映射到不同机器上。
|
完全虚拟化
|
使用一个完全虚拟化解决方案来容纳Docker,如KVM。如果容器内的内核漏洞被发现,这将防止其从容器扩大到宿主上。类似Docker-in-Docker工具,Docker镜像可以嵌套来提供该KVM虚拟层。
|
日志分析
|
收集并归档与Docker相关的安全日志来达到审核和监控的目的,一般建议使用rsyslog或stdout+ELK的方式进行日志收集、存储与分析,因为Docker本身要求轻量,所以不建议像虚拟机或者物理机上安装安全agent,这时实时威胁检测和事件响应功能就要依赖实时日志传输和分析了。可以在宿主上使用以下命令在容器外部访问日志文件:
docker run -v /dev/log:/dev/log /bin/sh
使用Docker内置命令:
docker logs ... (-f to follow log output)
日志文件也可以导出成一个压缩包实现持久存储:
docker export
|
漏洞扫描
|
前面的镜像安全,跟这里的漏洞扫描关联很密切,可以使用相同的工具去实现安全扫描,不过漏洞扫描更倾向于外部检测,镜像安全则需要镜像仓库和CI系统联动,始终不是一回事,所以分来介绍。 下面介绍5款用于Docker漏洞扫描的工具,它们各有千秋,从镜像到容器,从宿主到容器,从dockerfile到docker-compose,从安全基线检查与漏洞发现,从容器安全到性能优化,均有覆盖。 docker-slim: 参考:
https://github.com/docker-slim/docker-slim
创建小容器需要大量的巫术魔法,它可以是相当痛苦的。你不应该丢掉你的工具和你的工作流程。使用Docker应该很容易。docker-slim是一个容器的魔法减肥药。它将使用静态和动态分析为你的应用程序创建一个紧凑的容器。 Docker Bench for Security: 参考:
https://github.com/docker/docker-bench-security
Docker Bench for Security是一个脚本,用于检查在生产环境中部署Docker容器的几十个常见的最佳实践,测试都是自动化的,受CIS Docker 1.13基准的启发而来。 Clair: 参考:
https://github.com/coreos/clair
Clair是一个用于静态分析应用程序容器(目前包括appc和docker)中的漏洞的开源项目。基于k8s,将镜像上传到clair所在机器扫描即可。从已知的一组源连续导入漏洞数据,并与容器映像的索引内容相关联,以便产生威胁容器的漏洞的列表。当漏洞数据在上游发生变化时,可以传递通知,并且API会查询以提供漏洞的先前状态和新状态以及受这两者影响的图像。 Container-compliance: 参考:
https://github.com/OpenSCAP/container-compliance
Container-compliance是基于OpenSCAP的用于评估镜像、容器合规性的资源和工具。 Lynis: 参考:
https://cisofy.com/lynis/plugins/docker-containers/
lynis本身是一套Linux/Unix系统安全审计的shell脚本,执行时系统消耗很低。Lynis-docker是Lynis的一个插件,这个插件收集关于Docker配置和容器的信息。
|
端口扫描
|
很多人认为,容器被入侵带来的风险,远比不上物理机和传统虚拟机,于是他们直接把docker容器对外网开放,而且不配置任何访问控制。另外,也会存在宿主iptables错误调导致容器直接对外开放的问题存在,于是,这时针对容器进行快速批量的端口快速扫描显得很有必要。目前Nmap/Masscan这两款工具用的比较多。 Nmap支持tcp/udp端口扫描以及自定义插件扫描任意漏洞,是最著名、应用最广的端口扫描器。masscan的扫描结果类似于nmap,在内部,它更像scanrand, unicornscan, and ZMap,采用了异步传输的方式。它和这些扫描器最主要的区别是,它比这些扫描器更快。参考:
https://github.com/robertdavidg
|