渗透测试实战从靶场搭建到渗透流程——第 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「端口通、服务不通」的补全问题。

相关推荐
kingx312 天前
BugKu PRA 渗透测试 2(Harry‘s Blog):9 Flag 全链实战复盘
中间件·渗透测试·log4j2·内网渗透·反序列化
kingx312 天前
BugKu 渗透测试 4 实战:文件上传打点,5 Flag 全通
数据库·渗透测试·web·内网渗透
文章永久免费只为良心15 天前
Web应用安全与防护_第三章_日志文件包含_从一道 CTFshow 题目讲透「日志投毒型 LFI → RCE」:原理、时序陷阱与全变种攻防手册
android·网络安全·渗透测试·漏洞危害·漏洞描述·日志投毒·红队指南
IT大白鼠16 天前
渗透测试实战从靶场搭建到渗透流程——第 8 篇 · 服务型靶标(上):MySQL 双版本写文件链
数据库·mysql·渗透测试
sbjdhjd16 天前
从污点追踪断点到 PHP-FPM 请求队列:HIDS PHP WebShell 样本复盘
开发语言·网络安全·数据挖掘·渗透测试·开源·php·shell
能年玲奈喝榴莲牛奶17 天前
4zreark:只用 PostgreSQL 的资产侦察与漏洞管理平台,Go + React 全栈开源
网络安全·渗透测试·资产测绘·企业管理·资产收集
天府云创18 天前
Rustscan 端口扫描工具入门到实战
渗透测试·网络扫描·nmap·网络嗅探·rustscan·安全测速·企业攻防
admin and root18 天前
《神农安全.AI漏洞挖掘src赏金》单独开放!
安全·web安全·网络安全·数据挖掘·渗透测试·ai安全·白帽子黑客
IT大白鼠18 天前
渗透测试实战从靶场搭建到渗透流程——第 4 篇 · SQL 注入进阶:POST、请求头与绕过
渗透测试