Docker 漏洞靶场,究竟什么架构好?

phith0n 2021-03-14
vulhub 发布于 2021-03-14 03:03:10 阅读 2701 评论 0

我们常见的Docker漏洞靶场,通常会存在以下两个架构:

  • 将所有服务打包在一个镜像里,运行环境等于运行镜像
  • 使用compose等工具编排镜像,管理漏洞靶场服务

大家可能更熟悉的是后者,因为这是Vulhub所使用的架构。但是,我这篇文章为什么会又将这两者都提出来讲呢?

对Docker的认识

不少人在学习Docker乃至于更广义的容器知识的过程,可以分为三个阶段:

  • 初识:将容器理解为虚拟机的阶段
  • 偏执:认识到容器的特点,排斥将容器作为虚拟机使用的阶段
  • 和解:开始接受和允许将容器用做虚拟机的阶段

怎么理解这三个阶段?

当你初识容器的时候,你可能会惊叹,这个虚拟机可真好用,你可能会尝试在一个容器shell内安装各种Linux工具与服务,尝试使用docker save来保存你的阶段性成果,此时你可能并不真正了解容器和虚拟机的区别。

随着对容器的理解,你开始学习了Dockerfile和docker-compose等编排工具,你开始减少手工进入容器shell内的操作,开始使用Dockerhub内海量的官方或第三方镜像,来构造自己的”小内网“。此时,你可能开始瞧不起最初的自己,会觉得在一个容器内安装多个服务的人都是异端。

容器知识慢慢在你心中生根发芽,你已经熟练掌握容器的原理和各种工具使用方法,但有时候还是不禁会问问自己:什么是Docker与容器的哲学?你会发现,并不是所有服务都是完美的,有的应用依赖于多个底层服务,有数据库、定时任务、缓存、异步任务等等等等,你发现有些东西是无法拆分的。此时你开始和自己和解,其实也是更加深入理解了容器这个独立个体运行的方式。

我们并不需要偏执地必须将一个应用分割成一个个独立的进程,从而可以运行在独立的容器中,而是将应用切割成独立的逻辑个体,怎么理解呢?

比如一个Web应用,他需要使用Mysql数据库,也需要有一个定时任务,周期性地删除磁盘上的临时文件与数据库内的缓存。我们可以将其分成3个容器吗?可以但没必要。对于这个应用来说,Web服务应该和定时任务是同一个逻辑个体,他们所承载的功能就是运行Web,定时任务的目的是保证Web运行的稳定;而数据库是另一个逻辑个体,他的作用就是存储和查询。逻辑个体内部的服务是不能随意做更换的,但是多个逻辑个体可以做替换,比如,我们可以将Mysql从5.5升级到5.7,甚至替换成Postgresql。

所以,我们不应该强制要求一个容器只能跑一个进程,而是应该按照逻辑个体来编排容器。

不同编排方式对靶场的影响

回到本文的主题,靶场。漏洞靶场适合使用怎样的容器编排方式,是应”场“而异的。举几个简单例子。

  1. spring-data-commons远程命令执行漏洞
  2. Joomla SQL注入漏洞
  3. redis2未授权访问漏洞
  4. Gitlab远程代码执行漏洞

这是4种很典型的漏洞环境。

第1个,也是最常见的,漏洞就存在于这个服务本身,而服务也是简简单单的独立进程模式。这种情况自不必说,靶场只需要运行一个容器即可。

第2个,其实也非常常见,多见于依赖数据库的Web应用。这类靶场往往需要两个容器,但搭建起来实际上非常简单,只需要通过docker-compose这样的编排服务将2个容器编排在一起即可

第3个,虽然redis也是一个独立的服务,与1略有不同的是,其利用方式往往与操作系统有关。比如,redis2未授权访问中可以通过写入crontab配置或者sshd公钥来利用,对于独立的redis容器来说是没有这两个依赖的,但靶场需要尽可能模拟真实环境,所以就不得不网容器里塞进crond与sshd。

第4个,Gitlab这类大型Web应用,本身运行起来以后就会有多个进程,而漏洞(SSRF+CRLF Redis)也需要依赖于这些进程,我们很难将一个完整的Gitlab拆分成不同容器,更遑论在拆分的基础上复现漏洞。

显然,漏洞1、2适合于使用compose来构造靶场,简单快捷;漏洞3、4适合于用一个独立的镜像来构造靶场。

其实,如果不嫌麻烦,靶场开发者是可以将Gitlab这样的大型Web应用拆分成数个容器的,但是这样违背了靶场的一个关键原则:尽可能模拟真实环境。大部分情况下,SSRF攻击的是127.0.0.1:6379,而漏洞靶场攻击的却是172.17.0.2:6379,这实际上将靶场变成了一个题目。

在我看来,靶场是作用是让初学者简单了解某一种漏洞的表现形式、利用方法,或者让某些自动化工具具有自动化的测试环境,而不是出一道题目让使用者来猜怎么用,所以标准很重要。

实际上用Docker来构造靶场,是与我上述靶场的关键原则略有冲突的,很简单一个例子,网上不少POC使用curl回连来检测漏洞是否存在,而很多Docker靶场里根本没有curl命令,这就导致这些POC会执行失败。而事实上,大部分情况下实际目标环境内都有curl,这说明靶场失真了。

虽然你也可以说是POC没有考虑全面,没有考虑到curl不存在的情况了,但是再次重申一句话,靶场不是CTF题目,不应该去为难使用者,而应该尽可能模拟真实环境。

那么是不是就不要使用Docker构造靶场了呢?

稍微优雅一点的方法

当然不是,Docker的有点显而易见,即使有上述的不足,也无法改变其的统治地位。

那么如何尽可能地解决问题?

我这里给出一个我自己试用过的方案:https://github.com/phusion/baseimage-docke...

phusion/baseimage-docker是一个基于Ubuntu的迷你Docker镜像,他和普通的Ubuntu镜像的不同是:

  • 具有init管理的能力
  • 包含crontab、logrotate
  • 包含sshd
  • 包含常见工具(如curl)

这几点足以弥补上述大部分问题了。

但是他的缺点也是显而易见的,也是为什么Vulhub没有使用这个方案的原因:因为基础镜像不同,导致所有的Dockerfile需要重新编写,无法利用到社区里的大量环境,这个成本是开源项目无法接受的。但是对于商业项目来讲,成本可控的情况下,选择基于phusion/baseimage-docker来构建容器靶场也不失为一个好的方案。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!
请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!
phith0n 资深作者
未填写
  • 作者发布文章2
  • 作者收获粉丝5
  • 作者收到点赞0
  • 所有文章被收藏了0
  • 博客总访问量排行第12
  • 博客总访问量3843(每日更新)
查看所有博文