渗透测试实战从靶场搭建到渗透流程——第 1 篇 · 靶场宿主搭建:Docker 编排 15 个常驻靶场

目 录

一、规划先行:资源盘点与端口规划

[1.1 只读盘点](#1.1 只读盘点)

[1.2 端口规划](#1.2 端口规划)

[二、编写 docker-compose.yml](#二、编写 docker-compose.yml)

三、启动排障:四个最常见的坑

[坑 1:容器内 200,宿主机却连接被重置](#坑 1:容器内 200,宿主机却连接被重置)

[坑 2:Mutillidae 提示 Database Offline](#坑 2:Mutillidae 提示 Database Offline)

[坑 3:DVNA 容器启动即退](#坑 3:DVNA 容器启动即退)

[坑 4:大镜像拉取中途 unexpected EOF](#坑 4:大镜像拉取中途 unexpected EOF)

四、导航门户:一页看全所有靶场

五、一键验收:用数据说话

六、日常运维命令速查

[6.1 初始化速查(哪些靶场要「先点一次」)](#6.1 初始化速查(哪些靶场要「先点一次」))

[6.2 纪律提醒](#6.2 纪律提醒)

一、规划先行:资源盘点与端口规划

第 0 篇说过,靶场宿主是一台 Rocky Linux 9.8 虚拟机(10.10.10.240,主机名 pxg),Docker 承载 15 个常驻靶场容器。动手之前先做只读盘点,确认三件事:系统与 Docker 版本、资源余量、端口占用。

1.1 只读盘点

cat /etc/rocky-release # 确认系统版本

docker --version && docker compose version

free -h # 内存余量,决定能跑多少容器

df -h / # 磁盘余量,镜像很占空间

ss -tlnp # 已占用端口,避免冲突

盘点结论直接决定方案:2C/8G 机器跑 15 个轻量 Web 容器绰绰有余(实测内存占用约 4G),但 Metasploitable2 的老服务与 Vulhub 大镜像要按需管理。

1.2 端口规划

端口规划是本篇最重要的设计决策:全部 Web 靶场集中在 8081~8091,8090 留给导航门户;数据库靶标用 3307/3308/6380;Metasploitable2 的 12 个服务端口全部非标准映射,刻意避开宿主机自己的 22 和 80。

|-----------------|-----------------|----------------------------------------------------------------------------------|
| 端口段 | 用途 | 说明 |
| 8081~8089、8091 | Web 靶场 | DVWA/Juice Shop/bWAPP/Mutillidae/WebGoat/sqli-labs/upload-labs/pikachu/DVGA/DVNA |
| 8090 | 导航门户 | nginx 静态页,所有靶场入口一页看全 |
| 3307 / 3308 | MySQL 5.7 / 8.0 | 弱口令与写文件链靶标 |
| 6380 | Redis 未授权 | 无密码靶标 |
| 2121~5901 | Metasploitable2 | 12 个非标端口(SSH 走 2222,避开宿主 22) |

二、编写 docker-compose.yml

全部靶场用一份 docker compose 统一编排,放在独立 bridge 网络 pentest-net(172.20.0.0/16),与宿主机网络隔离;重启策略统一为 unless-stopped,宿主机重启后靶场自动恢复。工作目录约定为 /data/pentest/lab。

mkdir -p /data/pentest/lab && cd /data/pentest/lab

docker network create pentest-net --subnet 172.20.0.0/16

下面是编排文件的核心内容(节选自实际交付版本,逐容器定义):

version: "3"

networks:

pentest-net:

external: true

services:

dvwa:

image: vulnerables/web-dvwa

container_name: dvwa

ports: "8081:80"

networks: pentest-net

restart: unless-stopped

juice-shop:

image: bkimminich/juice-shop

container_name: juice-shop

ports: "8082:3000"

networks: pentest-net

restart: unless-stopped

bwapp:

image: raesene/bwapp

container_name: bwapp

ports: "8083:80"

networks: pentest-net

restart: unless-stopped

mutillidae:

image: citizenstig/nowasp

container_name: mutillidae

ports: "8084:80"

networks: pentest-net

restart: unless-stopped

webgoat:

image: webgoat/webgoat

container_name: webgoat

ports: "8085:8080"

networks: pentest-net

restart: unless-stopped

sqli-labs:

image: acgpiano/sqli-labs

container_name: sqli-labs

ports: "8086:80"

networks: pentest-net

restart: unless-stopped

upload-labs:

image: c0ny1/upload-labs

container_name: upload-labs

ports: "8087:80"

networks: pentest-net

restart: unless-stopped

pikachu:

image: area39/pikachu

container_name: pikachu

ports: "8088:80"

networks: pentest-net

restart: unless-stopped

dvga:

image: dolevf/dvga

container_name: dvga

environment:

WEB_HOST: "0.0.0.0" # 关键:默认监听 127.0.0.1,必须放开(见坑 1)

WEB_PORT: "5013"

ports: "8089:5013"

networks: pentest-net

restart: unless-stopped

dvna:

image: appsecco/dvna:sqlite # 关键:latest 标签需外接 MySQL,必须用 sqlite 标签(见坑 3)

container_name: dvna

ports: "8091:9090"

networks: pentest-net

restart: unless-stopped

mysql57:

image: mysql:5.7.44

container_name: mysql57

environment:

MYSQL_ROOT_PASSWORD: "root"

ports: "3307:3306"

networks: pentest-net

restart: unless-stopped

mysql80:

image: mysql:8.0.46

container_name: mysql80

environment:

MYSQL_ROOT_PASSWORD: "root"

ports: "3308:3306"

networks: pentest-net

restart: unless-stopped

redis-unauth:

image: redis:alpine

container_name: redis-unauth

ports: "6380:6379"

networks: pentest-net

restart: unless-stopped

portal:

image: nginx:alpine

container_name: portal

volumes: "./portal/index.html:/usr/share/nginx/html/index.html:ro"

ports: "8090:80"

networks: pentest-net

restart: unless-stopped

Metasploitable2 比较特殊:镜像自带的启动配置只拉起 4 个服务,需要外挂启动脚本,单独放第 2 篇讲。先把其余 14 个容器跑起来。

docker compose up -d

docker compose ps # 确认容器状态

三、启动排障:四个最常见的坑

「容器显示 Up」不等于「靶场能用」。这一节是全篇含金量最高的部分------四个坑都来自真实部署,且表象都极具误导性。

坑 1:容器内 200,宿主机却连接被重置

现象:DVGA 容器 Up、端口映射正常,但宿主机 curl 8089 直接报 Recv failure:连接被对方重设;进容器内访问 5013 却是 200。

根因:应用默认只监听容器内的回环地址 127.0.0.1,而 docker-proxy 是从容器网卡侧转发进来的,命中不了回环监听,于是直接 RST。解决办法就是在 compose 里注入环境变量把监听地址放开(上文 dvga 段的 WEB_HOST: "0.0.0.0")。

经验:凡「容器内能访问、宿主访问被 reset」,第一反应查应用监听地址是否 127.0.0.1,优先找它的 host/bind 配置项,而不是怀疑 Docker 端口映射或防火墙。

坑 2:Mutillidae 提示 Database Offline

现象:8084 页面能打开,顶部提示数据库离线;进容器 show databases 只有系统库。

根因:这个镜像不在启动时自动建库,站点根目录留了一个手动初始化页面。请求一次即可:

curl -s http://127.0.0.1:8084/set-up-database.php

回显连续出现 Executed query CREATE DATABASE ... result 1 即成功

注意一个细节:库名实际是 mutillidae,不是镜像名里的 nowasp,共建成 13 张表。页面上的 database-offline.php 只是提示页,不要被误导去改配置。同类问题也出现在 DVWA(setup.php 点 Create/Reset Database)和 bWAPP(install.php 点 install)。

坑 3:DVNA 容器启动即退

现象:dvna 容器启动几秒后退出,日志停在等待数据库连接。

根因:appsecco/dvna 的 latest 标签需要外接 MySQL,没有连接信息就一直等到失败。解决:换用自带 SQLite 的标签 appsecco/dvna:sqlite(上文已体现)。经验:拉「多形态」镜像前先确认标签,latest 往往不是自包含版本。

坑 4:大镜像拉取中途 unexpected EOF

现象:拉取 1GB 级镜像偶发中断,报 short read / unexpected EOF。解决:循环重试即可,Docker 分层缓存支持续传,已下载的层不会浪费;用 docker image inspect 判断是否拉齐。

四、导航门户:一页看全所有靶场

靶场一多,端口就记不住。写一个静态页挂到 8090,把地址、端口、默认口令整理成一张面板。在 /data/pentest/lab/portal/index.html 中做一个简单的表格页即可,每行一个靶场:

<!DOCTYPE html>

<html><head><meta charset="utf-8"><title>靶场导航门户</title></head>

<body><h1>渗透靶场导航门户 | 10.10.10.240</h1>

<table border="1" cellpadding="6">

<tr><th>靶场</th><th>地址</th><th>默认凭据</th></tr>

<tr><td>DVWA</td><td><a href="http://10.10.10.240:8081">:8081</a></td><td>admin / password</td></tr>

<tr><td>Juice Shop</td><td><a href="http://10.10.10.240:8082">:8082</a></td><td>无需登录</td></tr>

<!-- ...其余靶场按此格式补全... -->

</table></body></html>

门户页同时承担「健康面板」的职责:哪天发现某个入口打不开,直接进入第六节的排障流程。

五、一键验收:用数据说话

验收纪律只有一条:必须协议级验证。Docker 的端口发布由 docker-proxy 监听,容器内服务没起来,宿主机 TCP 照样能建连(假通),所以 HTTP 服务必须拿到状态码,不能只看端口通不通。

Web 靶场批量探活:拿 HTTP 状态码

for p in 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091; do

printf "%s -> %s\n" "

(curl -s -o /dev/null -w "%{http_code}" --max-time 10 -L http://10.10.10.240:"$p"/)"

done

非 HTTP 服务用 TCP 连通性判断,不要拿 curl 去测 FTP

for p in 3307 3308 6380; do

timeout 4 bash -c "echo >/dev/tcp/127.0.0.1/$p" 2>/dev/null \

&& echo "端口

p 关闭"

done

预期结果:8081~8091 全部返回 200 或 302(DVWA/bWAPP/DVNA 未登录时 302 跳登录属正常;WebGoat 根路径 404 属正常,入口是 /WebGoat/)。逐容器验证数据库类靶标:

docker exec mysql57 mysql -uroot -proot -N -e "select version();" # 5.7.44

docker exec mysql80 mysql -uroot -proot -N -e "select version();" # 8.0.46

docker exec redis-unauth redis-cli ping # PONG

全部通过后,在虚拟化软件层对宿主机打一次快照------这是「玩脏了随时回滚」的保险,也是本系列的固定习惯。

六、日常运维命令速查

|-----------------|------------------------------------------------------------------|
| 场景 | 命令 |
| 查看全部容器状态 | docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" |
| 编排视角查看 | cd /data/pentest/lab && docker compose ps |
| 重启单个靶场 | docker compose restart dvwa |
| 看某靶场日志 | docker logs --tail 20 dvwa |
| 修改了 compose 后生效 | docker compose up -d --force-recreate 容器名 |
| 临时停用某靶场 | docker stop dvwa |
| 资源余量检查 | free -h && df -h / |

6.1 初始化速查(哪些靶场要「先点一次」)

靶场分两类:自带数据型(sqli-labs、upload-labs、Juice Shop、DVGA,打开就能打)与要初始化型(DVWA、bWAPP、Mutillidae、pikachu,必须先跑一次安装页)。初始化入口如下:

|------------|----------------------------------------------------------|
| 靶场 | 初始化方式 |
| DVWA | 访问 /setup.php,点 Create/Reset Database(重置数据也用它) |
| bWAPP | 访问 /install.php,点 install(报 database already exists 属正常) |
| Mutillidae | 访问 /set-up-database.php,点 Setup/Reset the DB |
| pikachu | 访问 /install.php,点「安装/初始化」 |

6.2 纪律提醒

  • 宿主机 22/80 是系统自身端口,靶场端口规划必须避开。
  • 内存有限:不使用的 Vulhub 环境随用随起、用完即停,不要与常驻靶场抢内存。
  • 所有靶场仅限内网教学,绝不能映射到公网;玩脏了随时 docker restart 或重跑初始化,也可回滚快照。

宿主机就绪后,下一篇配置攻击机:给 Kali 固定 IP、装齐工具,并单独解决 Metasploitable2「端口通、服务不通」的补全问题。

相关推荐
墨云安全5 天前
系统安全检测方案怎么写?从资产清点到复测闭环的技术框架
安全·网络安全·渗透测试·系统安全
文章永久免费只为良心9 天前
Ctfshow_Web应用安全与防护_第二章_无字母数字命令执行
前端·python·安全·网络安全·渗透测试·ctf·红队渗透测试
墨云安全10 天前
AI 漏洞挖掘平台怎么评估?2026 年技术架构与选型要点
网络·人工智能·网络安全·架构·渗透测试
墨云安全10 天前
自动化渗透测试工具有哪些?2026 年引擎原理、任务编排与误报抑制实践
git·测试工具·网络安全·渗透测试·自动化
墨云安全11 天前
自动化安全测试工具的技术架构、集成方式与任务编排(2026 年实践)
人工智能·网络安全·渗透测试
墨云安全11 天前
AI 渗透测试是怎么实现的?2026 年大模型驱动测试用例生成的工程拆解
网络·人工智能·网络安全·渗透测试·测试用例
墨云安全12 天前
内网资产无法暴露到公网,怎么做安全检测?2026 年内网渗透测试的落地路径
开发语言·安全·网络安全·渗透测试·php
墨云安全15 天前
红队评估和渗透测试的区别是什么?2026 年从目标、方法到交付物的对比
网络·安全·web安全·网络安全·渗透测试
白猫不黑18 天前
AI自动化漏洞挖掘从入门到进阶超详细学习路线
人工智能·学习·web安全·网络安全·信息安全·渗透测试·自动化