0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Docker容器构建环境及安全措施分析

马哥Linux运维 来源:未知 作者:工程师郭婷 2018-07-31 16:03 次阅读

DevOps概念的流行跟近些年微服务架构的兴起有很大关系,DevOps是Dev(Development)和Ops(Operations)的结合,Dev负责开发,Ops负责部署上线,Docker出现之前,公司需要搭建一个数据库环境,有了Docker之后,只需在一些开源的基础镜像上构建出公司自己的镜像即可。

因此目前大多数DevOps设置都在CI管道中的某处设置了Docker,这就意味着你所看到的任何构建环境都将使用Docker等容器解决方案。由于这些构建环境需要接受不可信的用户提供的代码并进行执行,因此探讨如何将这些代码安全地装入容器就显得非常有意义。

在这篇文章中,我将探讨在构建环境中非常小的错误配置是如何产生严重的安全风险的。

需要注意的是,我并未在本文描述Heroku,Docker,AWS CodeBuild或容器中的任何固有漏洞,而是讨论了在查看基于Docker容器的多租户构建环境时发现的错误配置漏洞。在常规运行下,虽然Docker容器技术提供了非常稳定的安全默认设置,但是在特殊情况时,有时候小的错误配置就会导致严重安全风险。

特殊的构建环境

可能的特殊构建环境可以具有以下架构:

1.具有完全托管的生成服务,可编译源代码、运行测试以及生成可供部署的软件包——AWS CodeBuild;

2.Docker构建服务中的Docker容器;

Docker容器可以通过Dind(Docker-in-Docker,是让你可以在Docker容器里面运行Docker的一种方式)创建,因此,从理论上来说,你最终得到两个攻击者需要逃脱的容器。使用CodeBuild可进一步最小化攻击面,因为你拥有AWS提供的一次性容器,而且租户不会与对方的构建过程互动。

攻击者是如何控制构建过程的?

在大多数构建或CI管道中要做的第一件事就是创建一个包含你想要构建和部署的代码的Git仓库。然后这些代码将被打包并转移到构建环境,最后应用到docker构建过程。

通过查看构建服务,你通常可以通过两种方式配置容器,即通过Dockerfile或config.yml,这两种方法都与源代码有关。

其中有一个CI配置文件,我称之为config-ci.yml,如下图所示。

Docker容器构建环境及安全措施分析

在其它的构建过程开始之前,该文件将在构建过程中被转换为Dockerfile。如果你有明确指定要使用的Dockerfile环境,可以将config-ci.yml更改为以下内容。

Docker容器构建环境及安全措施分析

Dockerfile_Web和Dockerfile_Worker是源代码存储库中Dockerfiles的相对路径和名称,既然现在我已经提供了完整的构建信息,就可以开始构建了。构建通常是通过原始仓库上的代码上传来启动的。启动时,你会看到如下所示的输出内容。

Docker容器构建环境及安全措施分析

正如你所看到的,输出的内容有docker build -f Dockerfile。这些内容即对调试过程有用,又对于发现可能出现的攻击有用。

对预构建过程进行攻击

在进入docker构建之前,我首先想到的是尝试并中断构建过程,或者,我可以尝试将来自CodeBuild环境的文件链接到我的Docker构建的上下文中。

由于我已经控制了config-ci.yml文件的内容,更具体地说,我控制的是“要使用的Dockerfile的相对路径”,所以我可以尝试用一种老式攻击方法——目录遍历攻击。

第一个尝试就是试着改变构建的目录:

Docker容器构建环境及安全措施分析

一旦构建过程开始,我就会立即得到错误信息。

有趣的是,该错误是我造成的,并导致了路径泄漏,如果我尝试“读取”文件会发生什么?

Docker容器构建环境及安全措施分析

可以看出,我解析了Docker守护进程的错误。不幸的是,这只针对我系统上的第一行文件。尽管如此,这也是一个有趣的开始。

Docker容器构建环境及安全措施分析

其实,我这么做的另一个想法是想尝试使用符号链接将文件包含到我的构建中。不过,Docker阻止了我这么做,因为它不会将构建目录之外的文件包含到构建上下文中。

攻击构建过程,以发现漏洞

让我们先回到实际的构建过程,看看可以对什么进行攻击?由于构建过程发生在dind Docker容器中,该容器在一次性CodeBuild实例中运行。为了进一步寻找攻击,docker构建过程会在一次性Docker容器中运行所有命令。Docker的容器是把应用程序和环境打包在一起的,所以是一次构建,多处发布。举个例子,以前你开发完程序后,测试人员和运维人员都需要去部署,通过docker只需要一个run命令即可。因此docker最大的好处就是标准化了应用交互,同时支持多个不同平台和多个不同的云服务商,只要机器能装docker,就能无差别的运行程序。

所以Docker构建的每一步实际上都是一个新的Docker容器,这从构建过程的输出中就可以看出。

Docker容器构建环境及安全措施分析

在上述情况下,在新的Docker容器e7e10023b1fc中执行上面输出代码段中的Step 2/9。因此,即使用户决定在Dockerfile中插入一些恶意代码,它们也应该在一次性隔离容器中运行,而不会造成任何损害,如下所示。

Docker容器构建环境及安全措施分析

在发布Docker命令时,这些命令实际上被传递给负责创建/运行/管理Docker镜像的dockerd守护进程。为了继续实现dind,dind需要运行自己的Docker守护进程。然而,由于实现dind的方式是使用主机系统的docker实例(dockerd instance),以允许主机和后台共享Docker镜像,并从Docker的所有缓存中受益。

如果Dind使用下面的包装脚本启动会发生什么结果:

Docker容器构建环境及安全措施分析

/usr/local/bin/dind是一个使Docker在容器中运行的包装脚本,该包装脚本确保来自主机的Docker套接字在容器内部可用,因此,此特定配置会引入安全漏洞。

通常Docker构建过程将无法与Docker守护进程交互,但是,在这种情况下,却可以实现交互。敏锐的观察者可能会注意到,dockerd守护进程的TCP端口也是通过--host=tcp://0.0.0.0:2375进行映射的。通过这种错误配置设置的Docker守护进程会监控容器上的所有接口。因此,这就成了Docker网络功能中的一个漏洞。除非另有说明,否则所有容器都将会被放入相同的默认Docker网络中。这意味着每个容器都能够与其他容器进行通信,而不会受到阻碍。

现在,我的临时构建容器(执行用户代码的那个容器)已经能够向托管它的dind容器发出网络请求。由于dind容器只是重复使用了主机系统的Docker守护进程,所以我实际上是直接向主机系统AWS CodeBuild发出命令。

实施Dockerfiles攻击

为了测试Dockerfiles攻击,我可以将下面的Dockerfile提供给构建系统,这样我就能够交互访问正在构建的容器。需要说明的是,我这么做只是为了加速寻找漏洞的过程,而不是为了减少等待构建过程的时间。

Docker容器构建环境及安全措施分析

可以看出,反向shell可以通过很多不同的方式完成。

这个Dockerfile会安装一些依赖项,即docker和netcat。然后它们会将我的源代码目录中的文件复制到构建容器中。这将在后来的步骤中用到,除此之外,这么做还可以更容易地将我的完整漏洞快速传输到系统。由于mknod指令会创建一个文件系统节点,以允许通过文件重定向stdin和stdout。使用netcat可以打开一个反向shell,除此之外,我还需要在我使用公共IP地址控制的系统上为此反向shell设置监控器。

Docker容器构建环境及安全措施分析

这样,当构建发生时,我将收到一个反向连接。

Docker容器构建环境及安全措施分析

现在通过远程交互式访问,我就可以检查是否能对Docker守护进程进行访问。

Docker容器构建环境及安全措施分析

我会使用-H 172.18.0.1来指定远程主机,由于我发现Docker使用的网络范围是172.18.0.0/16,因此使用了此地址。为了找到这个远程主机,我的交互式shell被用来充作ip addr和ip route,以获得分配给我的构建容器的网络。请注意,默认情况下,所有Docker容器都将被放入同一个网络,默认网关将是运行Docker守护进程的实例。

Docker容器构建环境及安全措施分析

这样漏洞就会被成功发现,此时我可以从正在构建的容器中访问Docker,以便在下一步启动一个具有额外特权的新容器。

进行栈处理

此时,我已有一个shell,不过它还是位于一次性的构建容器中,作用不是很大。另外,我也可以访问Docker守护进程。于是我就想,把这两者结合起来会怎么样?为此,我引入了第二个Dockerfile,它会在构建和运行时创建一个反向shell。以下就是我启动第二个监控器来捕获的新的shell。

Docker容器构建环境及安全措施分析

这将作为Dockerfile2保存在源代码目录中,现在,当源代码文件被复制到构建容器中时,我可以直接访问它了。

当我重新运行构建过程时,我将在端口4445上获得我的第一个反向shell,这样我就可以留在构建容器中。现在我可以构建Dockerfile2,它被复制到COPY * /files/中的构建容器中。

Docker容器构建环境及安全措施分析

现在我可以使用主机Docker守护进程并构建一个新的可用Docker映像,我只需要运行它即可。不过这里有个小的技巧,就是我需要通将根目录映射到新的Docker容器,这可以通过-v/:/vhost完成。

以下是我得到的第一个反向shell:

Docker容器构建环境及安全措施分析

现在,一个新的反向shell就会连接到攻击系统上的4446端口。这样我就将处于一个新的容器中,并直接访问底层CodeBuild主机的文件系统和网络。这首先是因为--net=host将通过主机网络映射,而不是将容器保存在一个独立的隔离网络中。其次,因为Docker守护进程正在主机系统上运行,所以当使用-v /:/vhost的文件映射完成时,主机系统的文件系统将被映射。

Docker容器构建环境及安全措施分析

这样在新的反向shell中,我现在就可以探索底层的主机文件系统了。通过检查以下两个之间的区别,我就可以证明我在与此文件系统交互时不在Docker中。

在/vhost中我还发现有一个新的目录,它可以清楚地表明我在CodeBuild实例文件系统中,而不是在任何Docker容器中。

Docker容器构建环境及安全措施分析

这样在codebuild里,就会出现一个神奇的结果。这是AWS Codebuild用来控制构建环境的内容,快速浏览一下可以看到一些有趣的数据。

Docker容器构建环境及安全措施分析

此时,我通常会尝试提取AWS凭证和数据透视表,为此,我需要使用AWS_CONTAINER_CREDENTIALS_RELATIVE_URI。

Docker容器构建环境及安全措施分析

根据与该IAM相关的权限,现在应该有机会绕过AWS环境。

上述步骤可自动化实现,并且只需要一个反向shell即可完成,但是,请记住,你需要保持正常的构建环境。请注意,大多数构建环境会在30-60分钟后自动删除。

缓解措施

在这种情况下,修复非常简单,永远不要将Docker守护进程绑定到所有接口上。从包装脚本中删除--host=tcp://0.0.0.0:2375 行也可以来修复这个漏洞。另外,不需要绑定到TCP端口,因为unix套接字已经通过了--host=unix:///var/run/docker.sock映射。

总结

虽然容器策略提供了一个很好的机制,来让你创建运行不受信任代码的安全环境,而不需要额外的虚拟化过程。然而,这些容器的安全性与它们的配置一样。默认情况下,它们非常安全,但只需一个小的配置错误就可以让整个安全环境崩塌。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 微服务
    +关注

    关注

    0

    文章

    117

    浏览量

    7240
  • Docker
    +关注

    关注

    0

    文章

    435

    浏览量

    11596

原文标题:Docker容器构建过程的安全性分析

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    docker容器有几种状态

    Docker 是一种流行的容器化平台,它能够帮助开发人员将应用程序和其依赖打包成一个独立的容器,并且能够在不同的环境中进行部署和运行。在 Docke
    的头像 发表于 11-23 09:50 749次阅读

    docker核心组件有哪些

    Engine 是 Docker 的核心组件,它是一个轻量级的容器运行时环境。它包括 Docker 守护进程(dockerd)、客户端工具(dock
    的头像 发表于 11-23 09:47 701次阅读

    docker进入容器的方法有哪些

    Docker是一种流行的容器化平台,它能够快速构建、交付和运行应用程序。在使用Docker时,我们经常需要进入容器进行调试、管理和运行命令等
    的头像 发表于 11-23 09:45 3040次阅读

    docker容器容器之间通信

    Docker是一种轻量级容器化技术,能够将应用程序及其依赖项封装在一个独立、可移植的容器中。而容器化的应用程序通常是以分布式方式设计的,因此实现容器
    的头像 发表于 11-23 09:36 517次阅读

    docker容器删除后数据还在吗

    中的数据是否还会保留,这是一个需要深入分析和理解的问题。 本文将详细探讨Docker容器删除后数据的存储机制,从容器使用的存储驱动、数据卷、挂载以及网络等方面进行讲解,以帮助读者全面理
    的头像 发表于 11-23 09:32 625次阅读

    使用Docker容器编译OK3568源代码

    经常编译系统,又免不了搭建各种开发环境,所以为了不对开发主机的环境有影响,使用Docker容器编译代码是比较方便和省心的方式。 编译OK3568的源代码,需要用Ubunut 18.04
    发表于 10-19 10:36

    如何使用 Docker容器化技术

    对于开发人员来说,Docker肯定都不陌生,今天小编带大家重新学习一下Docker。 什么是 Docker 官话: Docker 是一种开源的容器
    的头像 发表于 09-30 11:24 9757次阅读

    如何判断是否在docker镜像中?

    实战中首先需要判断服务器是否为docker环境。常用的判断方法有两种。 1、通过执行 ls -alh /.dockerenv是否存在.dockerenv文件 docker环境下存在该文
    发表于 09-20 07:42

    docker基础知识和使用bmnnsdk时的docker常用命令

    的物理机上运行一样。有了 Docker,就不用担心环境问题。 1.2 image文件与容器container Docker 把应用程序及其依赖,打包在 image 文件里面。只有
    发表于 09-18 07:59

    smt加工焊接时需要注意几点安全措施

    一般在smt加工中,手工焊接是最常见的,但是焊接过程中要注意一些安全措施,才能更有效率的工作。
    的头像 发表于 09-15 09:14 621次阅读

    电容放电前安全措施

    电容放电前安全措施  电容放电前的安全措施是十分必要的,因为电容能够存储大量的电荷,电容内的电荷释放可能会引起电击、火灾等安全隐患。因此在进行电容放电之前,需要采取一系列安全措施来确保
    的头像 发表于 09-08 11:35 729次阅读

    【Milk-V Duo 开发板免费体验】2、SDK编译环境Docker镜像制作教程

    文件duoBuild.dockfile。 这里我已经制作好了,实际上脚本也没什么复杂的东西。简单来说,也就是FROM命令指定镜像的基础包。ENV命令设置镜像的环境变量。WORKDIR命令设置进入容器的默认路径(本镜像默认把源码挂载
    发表于 08-24 20:23

    docker容器构建yocto imx-image时出错怎么解决?

    我正在尝试根据规范 <>(修订版 LF5.15.5_1.0.0 — 2022 年 3 月 31 日)中的第 3.1 章 Dockerdocker 容器构建
    发表于 06-08 09:30

    将GPIO输出设置为高电平,然后将GPIO连接到GND,是否有任何安全措施

    您好, 如果我将 GPIO 输出设置为高电平,然后将 GPIO 连接到 GND,是否有任何安全措施? 任何事情都可能出错,或者不会有任何问题? 有人建议我应该在 GPIO 和 GND 之间使用一个 10K 的电阻作为电流限制,以避免损坏 GPIO Ps - GPIO 将用于连接按钮
    发表于 05-25 07:54

    知识角:电缆敷设施工方案及安全措施-科兰

    随着综合布线的普及,科兰小编为了帮助这些人,每天都会在官网进行一些相关知识分享,今天我们将围绕电缆敷设施工方案及安全措施这一主题展开阐述。 电缆敷设施工方案及安全措施--余量计算 1、提供给概算
    的头像 发表于 05-23 10:31 509次阅读