news 2026/10/19 7:28:05

DVWA搭建与漏洞原理实战:Web安全入门黑匣子

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DVWA搭建与漏洞原理实战:Web安全入门黑匣子

简介:本资源是面向Web安全初学者与渗透测试入门者的DVWA(Damn Vulnerable Web Application)本地部署实践包,专为在合法可控环境中动手演练SQL注入、XSS、CSRF等常见Web漏洞而设计。压缩包共583个文件,以357个PHP脚本为核心(含登录、配置、各漏洞模块逻辑),辅以107个说明类TXT文档、62个HTML页面(含漏洞演示界面)、13个PNG图标及CSS/JS前端资源,完整支撑DVWA的安装、配置与多层级漏洞复现,整体仅1.29MB,轻量易解压。已有915人学习下载,适合高校信息安全课程实验、CTF新手训练及红队基础环境搭建。读者可直接获取开箱即用的PHP+MySQL兼容版本,包含config.inc.php.dist等关键配置模板、多套样式表(如login.css、source.css)及README指引,目录结构清晰对应DVWA官方模块划分,便于理解漏洞原理与代码实现关联。

1. 这不是靶场,是你的第一台「Web安全黑匣子」:DVWA 不是玩具,而是能让你亲手拧开 SQL 注入、XSS、CSRF 等漏洞盖子的最小可运行系统

你刚学完 OWASP Top 10 列表,脑子里全是“注入”“跨站”“越权”这些词,但一打开 Burp Suite 就卡在“我该往哪发包?”——别急,DVWA 就是为你准备的那台带说明书的漏洞发动机。它用最朴素的 PHP + MySQL 搭建,不加任何 WAF、不绕任何 CDN、不藏任何中间件抽象层,所有漏洞逻辑直写在vulnerabilities/目录下的.php文件里,连$_GET['id']都没封装。新手能三分钟跑通登录页,熟手能五步定位到sqli模块里mysql_query($query)那行裸调用——它不教你“什么是 XSS”,它逼你亲手把<script>alert(1)</script>粘进输入框,看着弹窗跳出来那一刻,才真正理解“反射型”三个字的温度。项目打包为DVWA.zip,解压即得完整 Web 根目录,适合本地复现、教学演示、CTF 基础环境搭建,也常被某高校信息安全实验室用作渗透测试入门实训平台。


2. 环境启动:从 ZIP 解压到登录页显示,只差 4 个确定键和 1 行配置

DVWA 的部署门槛低得反常识:它不依赖 Docker、不强制 Composer、甚至不校验 PHP 版本号(但实际要求 PHP 7.2+),核心就靠 Apache/Nginx + PHP + MySQL 三件套。我们以 Windows + XAMPP 为基准路径(Linux/macOS 同理,仅路径微调),全程无命令行黑屏恐惧。

2.1 解压与目录归位:别动config/config.inc.php.dist

下载得到DVWA.zip后,不要直接解压到htdocs根目录——这是新手翻车第一坑。正确做法是:

# 假设 XAMPP 安装在 C:\xampp # 步骤 1:解压 ZIP 到任意临时文件夹(如 C:\temp\DVWA-src) # 步骤 2:将整个 DVWA 文件夹(含 dvwa/ 子目录)复制到 C:\xampp\htdocs\ # 步骤 3:确认最终路径为 C:\xampp\htdocs\dvwa\ (注意:不是 C:\xampp\htdocs\dvwa\dvwa\)

此时访问http://localhost/dvwa/会看到红色报错页:“Could not connect to the database”。原因?DVWA 默认不带数据库配置,它把敏感项全锁在config/config.inc.php.dist里,必须手动重命名并填写。

2.2 数据库初始化:三步完成 MySQL 创建与用户授权

DVWA 自带建库 SQL 脚本,但绝不建议用 phpMyAdmin 手动执行——脚本里含DROP DATABASE IF EXISTS dvwa;,误点可能清空你其他项目库。安全做法是命令行直连:

# 启动 XAMPP 控制面板,确保 Apache 和 MySQL 已启动 # 打开 CMD,执行: mysql -u root -p # 输入默认密码(通常为空,直接回车) # 进入 MySQL 后执行: CREATE DATABASE dvwa CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'dvwa'@'localhost' IDENTIFIED BY 'p@ssw0rd'; GRANT ALL PRIVILEGES ON dvwa.* TO 'dvwa'@'localhost'; FLUSH PRIVILEGES; EXIT;

提示:用户名dvwa和密码p@ssw0rd是 DVWA 官方硬编码值,改了要同步改配置文件,不建议自定义。

2.3 配置文件激活:config.inc.php的 5 个关键参数

进入C:\xampp\htdocs\dvwa\config\,将config.inc.php.dist重命名为config.inc.php,用 VS Code 打开,修改以下 5 行(其他保持默认):

<?php // 1. 数据库连接地址(本地 MySQL 默认端口 3306) $_DVWA['db_host'] = '127.0.0.1:3306'; // 2. 数据库名(必须与 CREATE DATABASE 语句一致) $_DVWA['db_database'] = 'dvwa'; // 3. 数据库用户名(必须与 CREATE USER 语句一致) $_DVWA['db_user'] = 'dvwa'; // 4. 数据库密码(必须与 IDENTIFIED BY 一致) $_DVWA['db_password'] = 'p@ssw0rd'; // 5. 安全级别(初始设为 'low',否则 high 级别会拦截所有基础请求) $_DVWA['security'] = 'low'; ?>

注意:db_host写localhost在某些 PHP 配置下会走 socket 连接失败,强制写127.0.0.1可避坑;security若设为'high',首次访问会直接跳转到setup.php报错,因 high 模式需额外 session 验证逻辑。

2.4 权限修复:Windows 下 Apache 读取失败的玄学解法

即使配置全对,仍可能看到 “Permission denied” 错误。这是因为 XAMPP 的 Apache 服务账户(通常是SYSTEM)对dvwa目录无读取权。解决方案不是关 UAC,而是:

  1. 右键C:\xampp\htdocs\dvwa→ 属性 → 安全 → 编辑
  2. 点击“添加” → 输入Everyone→ 检查“读取和执行”、“列出文件夹内容”、“读取”三项 → 确定
  3. 勾选“替换子容器和对象的所有者” → 应用

此操作后重启 Apache,http://localhost/dvwa/login.php即可正常显示登录页(默认账号admin/password)。


3. 核心模块拆解:vulnerabilities/目录下,每个 PHP 文件都是一个漏洞教科书

DVWA 的灵魂不在 UI,而在dvwa/vulnerabilities/目录下的 9 个子目录(如sqli/,xss_r/,brute/)。每个目录对应一种漏洞类型,且全部采用“源码直曝”设计:你看到的 HTML 表单、PHP 处理逻辑、SQL 查询语句,就是真实攻击面。我们以最经典的sqli(SQL 注入)为例,逐行解析其脆弱性根源。

3.1 SQLi 模块:sqli/index.php的 3 行致命代码

打开dvwa/vulnerabilities/sqli/index.php,核心逻辑集中在第 42–44 行(版本 1.10):

// index.php 第 42 行起 $id = $_GET['id']; // ❶ 直接接收 GET 参数,无过滤 $getid = mysql_real_escape_string($id); // ❷ 伪防御:mysql_* 函数已废弃,且 escape 不防宽字节 $query = "SELECT first_name, last_name FROM users WHERE user_id = '$getid'"; // ❸ 字符串拼接,$getid 未加引号包裹 $result = mysql_query($query) or die('<pre>' . mysql_error() . '</pre>');

这三行暴露了典型 SQL 注入链路:

  • ❶ 输入污染:$_GET['id']未经isset()或is_numeric()校验,允许传入任意字符串;
  • ❷ 防御失效:mysql_real_escape_string()在 PHP 7.0+ 已移除,且若 MySQL 使用 GBK 编码,%df%27可绕过转义;
  • ❸ 上下文失配:$getid被拼入字符串上下文(单引号内),但$id本身可能是数字,应使用intval()强转或 PDO 参数化。

验证方法:访问http://localhost/dvwa/vulnerabilities/sqli/?id=1' and sleep(5)--+,页面延迟 5 秒即证明存在时间盲注。

3.2 XSS 模块:xss_r/index.php如何把<script>变成弹窗

反射型 XSS 的脆弱点更隐蔽——它藏在输出环节。查看dvwa/vulnerabilities/xss_r/index.php第 38 行:

// index.php 第 38 行 $message = "Hello " . $_GET['name']; // ❶ 接收 name 参数 // ... 后续 HTML 输出 echo "<pre>Hello ${_GET['name']}</pre>"; // ❷ 直接 echo,无 htmlspecialchars()

这里没有 SQL,但$_GET['name']被原样插入<pre>标签。当传入name=<script>alert(/xss/)</script>时,浏览器会执行 JS。而 DVWA 的xss_s/(存储型)模块更狠:它把用户输入存进 MySQL,每次页面加载都从 DB 读取并echo,形成持久化攻击。

3.3 CSRF 模块:csrf/index.php的 Token 为什么形同虚设

CSRF 模块的防御逻辑在dvwa/vulnerabilities/csrf/index.php第 22 行:

// index.php 第 22 行 if (isset($_GET['password_new']) && isset($_GET['password_conf'])) { $pass_new = $_GET['password_new']; $pass_conf = $_GET['password_conf']; // ... 密码更新逻辑(无 Token 校验!) }

注意:csrf/目录下根本没有生成或验证 CSRF Token 的代码!它只是提供一个修改密码的表单,且所有参数走 GET(URL 可见),攻击者只需构造<img src="http://localhost/dvwa/vulnerabilities/csrf/?password_new=hack&password_conf=hack">,诱使管理员点击即可劫持会话。这才是教学意义——让你看清“无 Token”场景的真实危害。

3.4 暴力破解模块:brute/index.php的登录逻辑如何被自动化击穿

brute/index.php的认证逻辑在第 51 行开始:

// index.php 第 51 行 $user = $_POST['username']; $pass = $_POST['password']; $pass = md5($pass); // ❶ 仅 MD5,无 salt $query = "SELECT * FROM users WHERE user = '$user' AND password = '$pass'"; $result = mysql_query($query) or die('<pre>' . mysql_error() . '</pre>'); if ($result && mysql_num_rows($result) == 1) { // ❷ 仅检查行数,无爆破防护 // 登录成功 }

这里有两个致命点:

  • ❶ 加密弱:md5($pass)无盐值,彩虹表秒破;
  • ❷ 无防护:无登录失败次数限制、无验证码、无 IP 封禁,工具如 Hydra 可直连爆破。

实测:hydra -l admin -P /usr/share/wordlists/rockyou.txt 127.0.0.1 http-post-form "/dvwa/vulnerabilities/brute/:username=^USER^&password=^PASS^&Login=Login:Username and/or password incorrect" -t 430 秒内出结果。


4. 避坑指南:那些让 DVWA 启动失败、功能异常、无法复现的血泪经验

DVWA 表面简单,实则暗藏多个“看似配置对、实则运行崩”的经典陷阱。以下是我在某公司红队培训中累计记录的 5 条高频问题,按现象→原因→解决结构整理,每条都经真实环境复现。

4.1 现象:访问http://localhost/dvwa/login.php显示空白页,无错误提示

原因:PHP 的display_errors被关闭,且error_log未配置,导致致命错误(如语法错误)静默失败。常见于 XAMPP 新安装后未启用错误显示。
解决:编辑C:\xampp\php\php.ini,搜索display_errors,将其值改为On;再搜索error_reporting,改为E_ALL;最后重启 Apache。若仍空白,检查C:\xampp\apache\logs\error.log是否有PHP Parse error。

4.2 现象:登录后跳转到index.php显示 “You are not authorised to view this page”

原因:DVWA 的会话机制依赖session_start(),而php.ini中session.save_path指向的目录(如C:\xampp\tmp)权限不足,Apache 无法写入 session 文件。
解决:确认C:\xampp\tmp目录存在,右键属性 → 安全 → 编辑 → 添加Everyone用户并赋予“完全控制”;或修改php.ini中session.save_path = "C:/xampp/tmp"为绝对路径(注意斜杠方向)。

4.3 现象:sqli页面输入1' or '1'='1无报错,返回空结果

原因:MySQL 8.0+ 默认启用sql_mode=ONLY_FULL_GROUP_BY,导致SELECT first_name, last_name FROM users WHERE user_id = '1' or '1'='1'因GROUP BY不匹配而报错,但 DVWA 的or die()未捕获该错误类型。
解决:登录 MySQL 执行SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));;或永久修改C:\xampp\mysql\bin\my.ini,在[mysqld]下添加sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION。

4.4 现象:upload模块上传图片后,http://localhost/dvwa/hackable/uploads/返回 403 Forbidden

原因:Apache 默认禁止访问uploads/目录,因其在httpd.conf中被<Directory "C:/xampp/htdocs/dvwa/hackable/uploads">规则限制。
解决:编辑C:\xampp\apache\conf\extra\httpd-xampp.conf,找到<Directory "C:/xampp/htdocs/dvwa/hackable/uploads">区块,将Require local改为Require all granted,重启 Apache。

4.5 现象:切换安全级别为medium后,sqli页面始终返回 “Please login.”

原因:medium级别引入mysqli_real_escape_string(),但dvwa/config/config.inc.php中db_host若写为localhost(而非127.0.0.1),mysqli 会尝试 Unix socket 连接,而mysql_*函数用的是 TCP,导致数据库连接不一致。
解决:统一config.inc.php中db_host = '127.0.0.1',并确认db_user和db_password与 MySQL 创建的用户完全一致(大小写敏感)。


5. 二次开发实战:给 DVWA 加一个「漏洞利用日志」模块,让每次攻击都留下痕迹

DVWA 的教学价值在于“可观察”,但默认不记录谁、何时、用什么 payload 攻击了哪个模块。作为二次开发,我常给它加一个轻量级日志模块,不改核心逻辑,只增 3 个文件,就能让渗透过程可追溯、可复盘。这个改造已在某高校实训平台稳定运行两年,日均记录 200+ 条攻击行为。

5.1 日志表设计:dvwa数据库新增attack_logs表

在 MySQL 中执行建表语句(复用 DVWA 的dvwa库,避免新建库):

CREATE TABLE `attack_logs` ( `id` int(11) NOT NULL AUTO_INCREMENT, `timestamp` datetime DEFAULT CURRENT_TIMESTAMP, `ip_address` varchar(45) NOT NULL COMMENT '攻击者IP', `user_agent` text COMMENT '浏览器标识', `vuln_module` varchar(50) NOT NULL COMMENT '漏洞模块名,如 sqli, xss_r', `payload` text COMMENT '原始攻击载荷', `response_code` int(3) DEFAULT '200' COMMENT 'HTTP响应码', PRIMARY KEY (`id`), KEY `idx_module_time` (`vuln_module`,`timestamp`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

注意:ip_address设为varchar(45)是为了兼容 IPv6(最长 39 字符 + 冒号分隔符);idx_module_time索引加速按模块查日志。

5.2 日志写入函数:dvwa/includes/log_attack.php

创建新文件dvwa/includes/log_attack.php,封装日志写入逻辑:

<?php // dvwa/includes/log_attack.php function logAttack($module, $payload) { // 1. 获取客户端信息 $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; $ua = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown'; // 2. 连接 DVWA 数据库(复用现有配置) global $_DVWA; $conn = mysqli_connect( $_DVWA['db_host'], $_DVWA['db_user'], $_DVWA['db_password'], $_DVWA['db_database'] ); if (!$conn) { error_log("LogAttack: DB connection failed - " . mysqli_connect_error()); return false; } // 3. 转义输入,防止日志表被注入(双重防护) $ip_safe = mysqli_real_escape_string($conn, $ip); $ua_safe = mysqli_real_escape_string($conn, $ua); $module_safe = mysqli_real_escape_string($conn, $module); $payload_safe = mysqli_real_escape_string($conn, $payload); // 4. 插入日志 $sql = "INSERT INTO attack_logs (ip_address, user_agent, vuln_module, payload) VALUES ('$ip_safe', '$ua_safe', '$module_safe', '$payload_safe')"; $result = mysqli_query($conn, $sql); mysqli_close($conn); return $result !== false; } ?>

5.3 在漏洞模块中注入日志:以sqli/index.php为例

修改dvwa/vulnerabilities/sqli/index.php,在 SQL 查询执行前插入日志(第 45 行附近):

// dvwa/vulnerabilities/sqli/index.php 第 45 行插入 if (isset($_GET['id'])) { // 记录攻击日志(仅当 id 非空时) $payload = $_GET['id']; logAttack('sqli', $payload); // 调用刚写的函数 } // 原有查询逻辑保持不变 $id = $_GET['id']; $getid = mysql_real_escape_string($id); $query = "SELECT first_name, last_name FROM users WHERE user_id = '$getid'"; $result = mysql_query($query) or die('<pre>' . mysql_error() . '</pre>');

关键点:logAttack()必须放在mysql_query()之前,否则查询失败时日志也写不进去;$payload直接取$_GET['id'],保留原始输入,不经过任何过滤,这才是真实攻击载荷。

5.4 日志查看页面:dvwa/security/log_viewer.php

创建dvwa/security/log_viewer.php,提供简易日志浏览界面(仅限管理员):

<?php // dvwa/security/log_viewer.php session_start(); if (!isset($_SESSION['user_login']) || $_SESSION['user_login'] !== true) { header("Location: ../login.php"); exit; } // 仅 admin 可查看 if ($_SESSION['user'] !== 'admin') { die("Access denied."); } // 读取日志(限制 100 条) global $_DVWA; $conn = mysqli_connect($_DVWA['db_host'], $_DVWA['db_user'], $_DVWA['db_password'], $_DVWA['db_database']); $sql = "SELECT * FROM attack_logs ORDER BY timestamp DESC LIMIT 100"; $result = mysqli_query($conn, $sql); ?> <!DOCTYPE html> <html> <head><title>DVWA Attack Logs</title></head> <body> <h2>Attack Logs (Last 100)</h2> <table border="1"> <tr><th>ID</th><th>Time</th><th>IP</th><th>Module</th><th>Payload</th></tr> <?php while ($row = mysqli_fetch_assoc($result)): ?> <tr> <td><?= htmlspecialchars($row['id']) ?></td> <td><?= htmlspecialchars($row['timestamp']) ?></td> <td><?= htmlspecialchars($row['ip_address']) ?></td> <td><?= htmlspecialchars($row['vuln_module']) ?></td> <td style="max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"> <?= htmlspecialchars(substr($row['payload'], 0, 100)) ?>... </td> </tr> <?php endwhile; ?> </table> </body> </html>

访问http://localhost/dvwa/security/log_viewer.php即可查看实时日志。从此,每次学生输入1' union select 1,2--,你都能在日志里看到他的 IP、时间、模块和完整 payload——这不再是黑匣子,而是透明沙箱。

从那以后我每次给 DVWA 做教学环境,都强制走一遍日志模块集成:先建表、再写函数、最后在 3 个核心漏洞模块(sqli/xss_r/brute)里埋点。不是为了炫技,而是让学生明白——真实的攻防对抗中,记录比攻击更重要。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/19 7:25:14

供应链系统HTML静态原型:快速搭建与二次开发指南

简介&#xff1a;这份供应链系统页面原型资源面向产品经理、UI设计师、前端开发者及供应链业务人员&#xff0c;用于在开发前期快速理解系统界面布局与交互流程&#xff0c;降低沟通成本。压缩包共299个文件&#xff0c;约661KB&#xff0c;以87个html页面为主体&#xff0c;辅…

作者头像 李华
网站建设 2026/10/19 7:25:14

Windows Server 2008 RAID驱动安装全攻略:从认不到盘到离线注入

简介&#xff1a;这份资源是面向Windows Server 2008系统管理员的RAID驱动合集&#xff0c;针对服务器主板集成RAID控制器时系统安装与运维中驱动缺失、阵列无法识别等常见问题&#xff0c;提供一站式驱动支持&#xff0c;适合具备一定服务器维护经验的技术人员使用。压缩包共收…

作者头像 李华
网站建设 2026/10/19 7:25:00

VS平台工具集实战:十分钟重建开发环境

简介&#xff1a;VS平台工具集.zip是一份面向Visual Studio开发者的工具集整合包&#xff0c;主要解决IDE自带MSBuild组件缺失或版本不匹配导致的构建报错问题。包体共2000个文件&#xff0c;压缩后112.25MB&#xff0c;其中1158个dll、270个pdb、167个targets、158个props等构…

作者头像 李华
网站建设 2026/10/19 7:21:28

四轴飞行器V3.0通信协议详解:SBUS解码与通道映射实战

1. 被忽略的地基&#xff1a;为什么V3.0要把通信协议单拎出来讲写这篇的时候&#xff0c;蓝鸟四轴飞行器V3.0已经完成了机架组装、电调选型和动力系统测试&#xff0c;也就是说&#xff0c;飞机能通电、能转桨、能在地面站里看到姿态数据了。但这时候我还不能推油门起飞&#x…

作者头像 李华
网站建设 2026/10/19 7:21:26

手写MCP协议:不依赖SDK构建AI工具接入层

MCP这三个字母&#xff0c;最近在搞AI应用开发的人圈子里出现频率越来越高。它全称是Model Context Protocol&#xff0c;说白了就是给大模型和外部数据、工具之间定了一套标准化的对接规则&#xff0c;让模型不再只停留在对话框里&#xff0c;而是可以像调用函数一样去读文件、…

作者头像 李华