1. 项目概述:从“马卡巴卡”到实战靶场的蜕变
最近在安全圈子里,一个叫“makabaka的小推车靶场”的项目标题引起了我的注意。乍一看,这个名字有点无厘头,像是网络热梗和硬核技术的奇妙结合。“makabaka”这个发音,很容易让人联想到最近流行的“马卡巴卡”谐音梗,带着点轻松和戏谑的味道;而“小推车”则是一种非常接地气的意象,让人联想到搬运、装载和移动。当这两个元素和“靶场”这个信息安全领域的核心训练工具结合在一起时,就构成了一个非常有趣的命题:一个旨在降低安全技术学习门槛,让知识像用小推车搬运一样轻松、可移动、可复现的实战训练环境。
这个靶场本质上是一个集成了多种常见漏洞场景、攻击技术与防御演练的综合性网络安全实验平台。它不像一些大型企业级靶场那样庞大复杂,而是更侧重于“小推车”的灵活与便携理念——易于部署、场景独立、目标明确。无论是刚入门的安全爱好者,还是想巩固某方面技能的从业者,都可以通过这个靶场,在一个安全、可控的环境里进行“实战”,从SQL注入、跨站脚本(XSS)到权限提升、内网渗透,一步步推着你的“知识小推车”前进。接下来,我将结合自己多年的渗透测试与安全研究经验,为你深度拆解如何从零开始构建并玩转这样一个极具个人特色的实战靶场。
2. 靶场核心设计思路与架构选型
构建一个靶场,首要问题不是急于安装软件或部署漏洞,而是想清楚它的定位和服务对象。makabaka的小推车靶场这个标题已经暗示了它的风格:轻量、模块化、富有趣味性且易于迭代。
2.1 设计哲学:为什么是“小推车”?
传统的靶场,无论是DVWA、WebGoat还是自己搭建的复杂内网环境,往往存在几个痛点:环境依赖重,搭建过程繁琐;场景固化,更新扩展麻烦;一次部署,难以在多台机器或不同时间段快速复现。而“小推车”的理念恰恰是针对这些痛点:
- 容器化与可移植性:就像小推车可以装载不同的货物并轻松移动,靶场的每个漏洞场景都应该是一个独立的、标准化的“集装箱”。Docker容器技术是实现这一理念的绝佳选择。每个漏洞应用(例如一个存在SQL注入的博客系统)打包成一个Docker镜像,配合
docker-compose编排,可以实现一键启停、版本管理和环境隔离。 - 模块化与积木化:“小推车”上的货物可以随时更换。靶场不应是一个庞然大物,而应由多个独立的、功能单一的漏洞模块组成。学习者可以根据自己的学习路径,像搭积木一样,选择今天练习“认证绕过”模块,明天练习“文件上传”模块,互不干扰。
- 低门槛与引导性:“小推车”意味着上手简单。靶场除了提供漏洞环境,更应配备清晰的学习指引、难度分级和提示系统。对于makabaka这样的趣味性项目,甚至可以设计一些剧情化的挑战说明,让学习过程像游戏闯关一样,降低初学者的畏难情绪。
2.2 技术栈选型:稳定、高效、易维护
基于以上设计思路,我选择了以下技术栈来搭建靶场的骨架:
- 核心引擎:Docker + Docker Compose。这是实现环境隔离和便携性的基石。所有靶机、漏洞应用、甚至网络拓扑(如将Web服务器和数据库放在不同容器,模拟真实环境)都通过Docker容器来定义。
- 漏洞应用来源:
- 经典集成:直接使用成熟的漏洞平台镜像,如
vulhub/vulhub项目中的单个漏洞环境。它提供了海量的、复现最新漏洞的Docker Compose配置,是极佳的“货物”来源。 - 自主构建:对于想深入理解漏洞原理的模块,我会用PHP、Python或Node.js编写简单的、存在特定漏洞的Web应用,并为其制作Dockerfile。这是体现“makabaka”个人特色的关键部分。
- 经典集成:直接使用成熟的漏洞平台镜像,如
- 编排与访问入口:Nginx反向代理。当有多个靶场应用同时运行时,我们不可能记住每个容器随机映射的端口。通过一个统一的Nginx,配置基于子域名或路径的转发规则(例如
sqli.makabaka.local-> 容器A,xss.makabaka.local-> 容器B),可以让访问变得非常优雅和方便。 - 辅助与监控:
- 数据库:根据漏洞场景需要,运行MySQL、PostgreSQL或Redis容器。
- 监控(可选):运行一个
Portainer容器来可视化管理和监控所有Docker容器,对于管理靶场非常直观。
注意:所有操作均在本地或授权的虚拟化环境中进行。绝对禁止在公网或未授权环境中部署漏洞应用,这不仅是法律红线,也是安全从业者的基本伦理。
2.3 目录结构规划
清晰的目录结构是项目可维护性的保障。我的“小推车”靶场目录树大致如下:
makabaka-range/ ├── docker-compose.yml # 总编排文件,定义网络、公共服务 ├── nginx/ │ ├── Dockerfile # 定制Nginx镜像(如需) │ └── conf.d/ │ └── range.conf # Nginx反向代理配置 ├── scenarios/ # “小推车”上的各个“货物”模块 │ ├── 01-sqli-basic/ # 基础SQL注入场景 │ │ ├── docker-compose.yml # 该场景独立的编排文件 │ │ ├── src/ # 漏洞应用源代码 │ │ │ └── index.php │ │ ├── Dockerfile # 构建该应用的镜像 │ │ └── README.md # 挑战说明、攻略、知识点 │ ├── 02-xss-reflected/ # 反射型XSS场景 │ │ └── ... │ ├── 03-file-upload/ # 文件上传漏洞场景 │ │ └── ... │ └── 04-cve-2024-xxxx/ # 复现某个特定CVE漏洞 │ └── ... ├── data/ # 挂载卷,持久化数据库数据等 └── scripts/ # 辅助脚本,如初始化、备份、重置 └── init-range.sh这种结构允许每个scenario(场景)高度自治,可以独立运行(cd scenarios/01-sqli-basic && docker-compose up),也可以被主docker-compose.yml引用,统一启动。
3. 实战构建:从零打造你的第一个漏洞模块
理论说再多不如动手做一遍。让我们以构建一个基础数字型SQL注入靶场为例,展示如何将想法落地。
3.1 漏洞应用开发
首先,在scenarios/01-sqli-basic/src目录下,创建一个极简但漏洞点清晰的PHP应用。
文件:index.php
<?php // 模拟一个简单的用户查询功能,存在数字型SQL注入漏洞 error_reporting(0); header("Content-Type: text/html; charset=utf-8"); $servername = getenv('MYSQL_HOST') ?: "db"; // Docker Compose中的服务名 $username = getenv('MYSQL_USER') ?: "root"; $password = getenv('MYSQL_PASSWORD') ?: "password"; $dbname = getenv('MYSQL_DATABASE') ?: "vulndb"; // 创建连接 $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); } $id = $_GET['id'] ?? 1; // 漏洞点:未对用户输入的id进行任何过滤 $sql = "SELECT * FROM users WHERE id = $id"; // 直接拼接,致命漏洞! $result = $conn->query($sql); echo "<h1>用户查询系统</h1>"; echo "<p>查询ID为 <strong>$id</strong> 的用户信息。</p>"; if ($result && $result->num_rows > 0) { echo "<table border='1'><tr><th>ID</th><th>用户名</th><th>邮箱</th></tr>"; while($row = $result->fetch_assoc()) { echo "<tr><td>".$row["id"]."</td><td>".$row["username"]."</td><td>".$row["email"]."</td></tr>"; } echo "</table>"; } else { echo "未找到该用户或查询出错。"; if ($conn->error) { echo "<br><small>错误信息: " . $conn->error . "</small>"; // 故意显示错误,方便初学者理解 } } $conn->close(); ?>这个应用的核心漏洞在于第13行,$id直接从$_GET获取并拼接进SQL语句,攻击者可以通过构造id=1 OR 1=1 --这样的参数来实施注入。
3.2 Docker化封装
为了让这个应用能像“货物”一样被“小推车”装载,我们需要为其编写Dockerfile和docker-compose.yml。
文件:Dockerfile
# 使用官方PHP镜像,带Apache服务器 FROM php:8.1-apache # 安装MySQL扩展(mysqli) RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli # 将我们的漏洞应用源代码复制到容器内的网站根目录 COPY src/ /var/www/html/ # 修改Apache配置,允许.htaccess重写(如果需要的话)并调整文件权限 RUN a2enmod rewrite && \ chown -R www-data:www-data /var/www/html && \ chmod -R 755 /var/www/html EXPOSE 80文件:docker-compose.yml(场景独立版)
version: '3.8' services: web: build: . ports: - "8081:80" # 映射主机8081端口到容器80端口 environment: MYSQL_HOST: db MYSQL_USER: root MYSQL_PASSWORD: password MYSQL_DATABASE: vulndb depends_on: - db networks: - sqli-net db: image: mysql:8.0 restart: always environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: vulndb volumes: - ./init.sql:/docker-entrypoint-initdb.d/init.sql # 初始化数据库表和数据 - mysql-data:/var/lib/mysql networks: - sqli-net # 安全考虑:仅限内部网络访问,不暴露端口到主机 # ports: # - "3306:3306" networks: sqli-net: driver: bridge volumes: mysql-data:文件:init.sql(数据库初始化脚本)
CREATE DATABASE IF NOT EXISTS vulndb; USE vulndb; CREATE TABLE users ( id INT PRIMARY KEY, username VARCHAR(50), email VARCHAR(100) ); INSERT INTO users (id, username, email) VALUES (1, 'admin', 'admin@makabaka.local'), (2, 'alice', 'alice@example.com'), (3, 'bob', 'bob@example.com');3.3 运行与测试
进入scenarios/01-sqli-basic目录,执行命令:
docker-compose up -d等待镜像构建和容器启动完成后,在浏览器访问http://localhost:8081/?id=1,你应该能看到用户admin的信息。
现在,进行SQL注入测试:
- 探测漏洞:访问
http://localhost:8081/?id=1 AND 1=1,页面应正常显示id=1的用户。 - 确认注入:访问
http://localhost:8081/?id=1 AND 1=2,页面应显示“未找到该用户”。因为1=2为假,整个查询条件不成立。 - 联合查询:尝试获取所有用户。首先需要判断列数:
http://localhost:8081/?id=1 ORDER BY 3--(正常)http://localhost:8081/?id=1 ORDER BY 4--(报错) => 说明共3列。 - 实施攻击:使用联合查询注入:
http://localhost:8081/?id=-1 UNION SELECT 1, database(), user()--页面会显示当前数据库名(vulndb)和数据库用户(root@%)。
至此,一个最基础的SQL注入漏洞模块就构建并验证成功了。通过这个过程,你不仅创建了一个靶标,更深刻理解了漏洞产生的代码层面原因。
4. 靶场统一管理与访问入口配置
当“小推车”上的“货物”(漏洞模块)多起来后,逐个访问不同的端口(8081, 8082...)非常不友好。我们需要一个统一的“调度中心”,这就是Nginx反向代理的作用。
4.1 配置主编排文件
在项目根目录 (makabaka-range/) 创建主docker-compose.yml,用于启动核心基础设施。
version: '3.8' services: nginx-proxy: image: nginx:alpine container_name: makabaka-nginx ports: - "80:80" - "443:443" # 如果需要HTTPS volumes: - ./nginx/conf.d:/etc/nginx/conf.d:ro # 挂载代理配置 - ./nginx/html:/usr/share/nginx/html:ro # 可选,挂载一个漂亮的导航页 - ./nginx/logs:/var/log/nginx # 挂载日志 networks: - range-network restart: unless-stopped portainer: image: portainer/portainer-ce:latest container_name: makabaka-portainer restart: unless-stopped ports: - "9000:9000" volumes: - /var/run/docker.sock:/var/run/docker.sock - portainer_data:/data networks: - range-network # 建议仅本地访问,或设置强密码 networks: range-network: driver: bridge name: makabaka-range-net # 给网络命名,方便其他场景加入 volumes: portainer_data:4.2 配置Nginx反向代理规则
在./nginx/conf.d目录下创建range.conf:
# 上游服务器定义,指向各个漏洞场景的容器服务名 upstream sqli_basic { server scenarios-01-sqli-basic-web-1:80; # 注意:服务名由docker-compose项目名和service名生成 } upstream xss_reflected { server scenarios-02-xss-reflected-web-1:80; } server { listen 80; server_name makabaka.local; # 本地测试域名,需要在hosts文件添加 127.0.0.1 makabaka.local # 默认首页,可以做一个导航页 location / { root /usr/share/nginx/html; index index.html; } # 根据路径转发到不同的靶场 location /sqli/ { proxy_pass http://sqli_basic/; # 注意结尾的斜杠,会将/sqli/后面的路径传递过去 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /xss/ { proxy_pass http://xss_reflected/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # 也可以使用子域名方式(需配置泛域名解析或hosts多条记录) # server_name sqli.makabaka.local; # location / { # proxy_pass http://sqli_basic; # ...其他header设置 # } }4.3 修改场景编排文件以接入主网络
为了让主Nginx能访问到各个场景的容器,需要修改每个场景的docker-compose.yml,让其加入主编排文件定义的网络,并移除端口映射(因为现在通过Nginx内部访问)。
以SQL注入场景为例,修改后的scenarios/01-sqli-basic/docker-compose.yml:
version: '3.8' services: web: build: . # 移除 ports 映射,不直接暴露给主机 # ports: # - "8081:80" environment: MYSQL_HOST: db MYSQL_USER: root MYSQL_PASSWORD: password MYSQL_DATABASE: vulndb depends_on: - db networks: - default # 场景内部网络 - makabaka-range-net # 加入主靶场网络 db: image: mysql:8.0 restart: always environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: vulndb volumes: - ./init.sql:/docker-entrypoint-initdb.d/init.sql - mysql-data:/var/lib/mysql networks: - default # 数据库只需在场景内部网络,无需暴露给主网络 networks: default: driver: bridge makabaka-range-net: external: true # 声明使用外部已存在的网络 name: makabaka-range-net volumes: mysql-data:4.4 启动与访问
- 启动主基础设施:在项目根目录执行
docker-compose up -d,启动Nginx和Portainer。 - 启动特定场景:进入某个场景目录,如
cd scenarios/01-sqli-basic,执行docker-compose up -d。 - 配置本地Hosts:编辑你电脑的
hosts文件(Windows在C:\Windows\System32\drivers\etc\hosts, Linux/Mac在/etc/hosts),添加一行:127.0.0.1 makabaka.local - 访问靶场:
- 导航页:
http://makabaka.local - SQL注入靶场:
http://makabaka.local/sqli/?id=1 - Portainer管理界面:
http://localhost:9000(首次访问需创建管理员账号)
- 导航页:
现在,你的“makabaka的小推车靶场”就有了一个统一的访问入口,结构清晰,管理方便。
5. 靶场内容规划与进阶场景设计
一个优秀的靶场不仅要有技术骨架,更要有精心设计的内容。我们可以按照OWASP Top 10、常见攻击手法等维度来规划“小推车”上的“货物”。
5.1 基础Web漏洞模块
这是靶场的核心,适合所有初学者。
| 模块编号 | 漏洞类型 | 难度 | 核心知识点 | 实现要点 |
|---|---|---|---|---|
| SC-01 | 数字型/字符型SQL注入 | 初级 | 联合查询、报错注入、布尔/时间盲注、堆叠查询 | 设计不同的过滤和错误回显方式。字符型重点练习闭合引号。 |
| SC-02 | 反射型/存储型/DOM型XSS | 初级-中级 | 脚本构造、事件处理器、编码绕过、CSP绕过 | 分别实现三种类型。存储型需结合数据库。增加简单的过滤器(如<script>过滤)供绕过。 |
| SC-03 | 文件上传漏洞 | 初级-中级 | 前端绕过、MIME类型检查、文件头检查、解析漏洞(.htaccess, .user.ini) | 设计多道关卡,逐步增加防护措施,让练习者层层突破。 |
| SC-04 | 命令执行/代码执行 | 中级 | 系统命令拼接、危险函数(eval, system)、反序列化、模板注入 | PHP的eval()、Python的os.system()、Java的反序列化链构造。 |
| SC-05 | 目录遍历/文件包含 | 初级 | 相对路径/绝对路径、NULL字节截断、PHP伪协议(php://filter, zip://) | LFI到RCE的转化是重点练习方向。 |
| SC-06 | 不安全的直接对象引用(IDOR) | 初级 | 参数预测、权限校验缺失 | 设计一个用户系统,通过修改URL中的user_id参数访问他人数据。 |
| SC-07 | 服务器端请求伪造(SSRF) | 中级 | 协议利用(file://, gopher://, dict://)、内网探测、绕过技巧 | 实现一个可以发起网络请求的功能,并尝试读取本地文件或攻击内网Redis。 |
5.2 权限提升与内网渗透模块
这部分模拟真实攻防场景,难度较高。
| 模块编号 | 场景主题 | 难度 | 核心目标 | 环境设计 |
|---|---|---|---|---|
| SC-08 | Linux系统提权 | 高级 | 从Web Shell获取www-data权限,提权至root | 靶机故意配置SUID文件、内核漏洞、Cron任务错误、sudoers配置错误等。 |
| SC-09 | Windows系统提权 | 高级 | 从普通用户权限提权至SYSTEM | 利用错误的服务配置、可写路径、令牌窃取、未打补丁的漏洞(如PrintNightmare)。 |
| SC-10 | 简单内网渗透 | 高级 | 突破边界,横向移动,获取域控权限 | 设计2-3台主机的简单内网:一台DMZ区Web服务器(入口点),一台内部文件服务器,一台域控制器。考察信息收集、漏洞利用、哈希传递、横向移动。 |
5.3 漏洞复现与CTF挑战模块
紧跟安全动态,复现真实世界的漏洞。
- SC-11:Log4j2 (CVE-2021-44228) 复现:搭建一个使用脆弱Log4j2版本的Java Web应用,练习JNDI注入和LDAP利用。
- SC-12:Spring4Shell (CVE-2022-22965) 复现:部署存在漏洞的Spring Boot应用,利用数据绑定机制进行RCE。
- SC-13:自定义CTF挑战:设计一些需要综合运用多种技巧的谜题。例如,一个登录框,需要先通过SQL注入获取管理员密码的MD5,然后破解MD5(或利用二次注入),最后结合XSS盗取Cookie完成登录。
每个模块都应配备详细的README.md,内容包括:场景描述、学习目标、难度等级、启动方式、访问地址、解题思路(可折叠隐藏)以及深入的技术原理分析。
6. 运维、安全与最佳实践
一个长期运行的靶场,需要考虑运维便利性和自身安全性。
6.1 自动化脚本与运维
编写Shell或Python脚本,让靶场管理变得轻松。
- 初始化脚本 (
scripts/init-range.sh):一键安装Docker和Docker Compose,拉取基础镜像,配置本地hosts。#!/bin/bash echo "[*] 初始化 makabaka的小推车靶场..." # 检查并安装Docker # 检查并安装Docker Compose # 创建必要的目录 # 添加hosts记录(询问用户确认) echo "[+] 初始化完成!" - 场景管理脚本 (
scripts/scenario-ctl.sh):统一启动、停止、重置所有或指定场景。#!/bin/bash ACTION=$1 SCENARIO=$2 case $ACTION in "start") if [ -z "$SCENARIO" ]; then echo "[*] 启动所有场景..." find ./scenarios -name "docker-compose.yml" -execdir docker-compose up -d \; else cd "./scenarios/$SCENARIO" && docker-compose up -d fi ;; "stop") # ... 类似逻辑 ;; "reset") # 重置数据库等状态 cd "./scenarios/$SCENARIO" && docker-compose down -v && docker-compose up -d ;; *) echo "用法: $0 {start|stop|reset} [场景目录名]" ;; esac - 备份与恢复脚本:定期备份数据库卷和配置文件。
6.2 靶场自身安全加固
切记,靶场是用于合法学习的。必须确保其不会意外暴露或成为攻击跳板。
- 网络隔离:所有靶场容器都应运行在独立的Docker网络中(如我们创建的
makabaka-range-net),绝不将数据库、SSH等服务的端口映射到主机公网IP(0.0.0.0)。仅通过Nginx反向代理暴露必要的Web端口(80/443),且Nginx本身只绑定127.0.0.1或本地访问。 - 最小化镜像:使用Alpine等小型基础镜像构建漏洞应用,减少攻击面。
- 定期更新:定期更新基础镜像(如
nginx:alpine,mysql:8.0)以修复已知漏洞。 - 访问控制:可以在Nginx层面配置简单的HTTP Basic认证,或者为Portainer设置强密码。更严格的情况下,可以配置仅允许本地或特定IP段访问。
- 资源限制:在
docker-compose.yml中为容器设置CPU和内存限制,防止某个漏洞利用练习耗尽主机资源。services: web: # ... 其他配置 deploy: resources: limits: cpus: '0.5' memory: 512M - 日志审计:收集Nginx和各个应用的访问日志、错误日志,定期审查,了解靶场被访问的情况。
6.3 学习路径与引导设计
为了让“小推车”更好推,学习路径至关重要。我建议在靶场的导航页(nginx/html/index.html)做如下设计:
- 新手村:按顺序排列SC-01到SC-07,每个模块完成后再解锁下一个。
- 进阶区:集中放置SC-08到SC-10等权限提升和内网渗透场景。
- 挑战营:放置漏洞复现和综合CTF场景。
- 知识库:每个场景的README中,除了攻略,还应包含“扩展阅读”部分,链接到OWASP备忘单、相关CVE详情、优秀技术文章等。
在每个漏洞应用的界面上,可以添加一个“提示”按钮,分等级给出提示。例如:
- 提示1:这个输入点似乎直接拼接到了数据库查询中。
- 提示2:试试在输入后加上一个单引号
‘。 - 提示3:查看页面返回的错误信息,它可能泄露了数据库结构。
这种设计能有效平衡挑战性和学习效率,避免初学者在第一步就卡住而放弃。
构建和维护一个像“makabaka的小推车”这样的靶场,本身就是一个极佳的学习过程。它迫使你去深入理解每一个漏洞的成因、利用方式和修复方案。当你能够流畅地向别人解释你靶场里的每一个挑战时,你对这些安全知识的掌握就已经超越了大多数纸上谈兵者。这个靶场不仅是你的练习场,更是你技术能力的立体名片。现在,就动手打造属于你自己的那辆“小推车”吧,从第一个简单的SQL注入模块开始,一步步把它装满。