恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
DVWA搭建与漏洞原理实战:Web安全入门黑匣子
首页
资讯中心
/
DVWA搭建与漏洞原理实战:Web安全入门黑匣子
DVWA搭建与漏洞原理实战:Web安全入门黑匣子
发布时间:2026/10/19 7:28:36
简介本资源是面向Web安全初学者与渗透测试入门者的DVWADamn Vulnerable Web Application本地部署实践包专为在合法可控环境中动手演练SQL注入、XSS、CSRF等常见Web漏洞而设计。压缩包共583个文件以357个PHP脚本为核心含登录、配置、各漏洞模块逻辑辅以107个说明类TXT文档、62个HTML页面含漏洞演示界面、13个PNG图标及CSS/JS前端资源完整支撑DVWA的安装、配置与多层级漏洞复现整体仅1.29MB轻量易解压。已有915人学习下载适合高校信息安全课程实验、CTF新手训练及红队基础环境搭建。读者可直接获取开箱即用的PHPMySQL兼容版本包含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”它逼你亲手把scriptalert(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 dvwalocalhost IDENTIFIED BY pssw0rd; GRANT ALL PRIVILEGES ON dvwa.* TO dvwalocalhost; FLUSH PRIVILEGES; EXIT;提示用户名dvwa和密码pssw0rd是 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] pssw0rd; // 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而是右键C:\xampp\htdocs\dvwa→ 属性 → 安全 → 编辑点击“添加” → 输入Everyone→ 检查“读取和执行”、“列出文件夹内容”、“读取”三项 → 确定勾选“替换子容器和对象的所有者” → 应用此操作后重启 Apachehttp://localhost/dvwa/login.php即可正常显示登录页默认账号admin/password。3. 核心模块拆解vulnerabilities/目录下每个 PHP 文件都是一个漏洞教科书DVWA 的灵魂不在 UI而在dvwa/vulnerabilities/目录下的 9 个子目录如sqli/,xss_r/,brute/。每个目录对应一种漏洞类型且全部采用“源码直曝”设计你看到的 HTML 表单、PHP 处理逻辑、SQL 查询语句就是真实攻击面。我们以最经典的sqliSQL 注入为例逐行解析其脆弱性根源。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/?id1 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 preHello ${_GET[name]}/pre; // ❷ 直接 echo无 htmlspecialchars()这里没有 SQL但$_GET[name]被原样插入pre标签。当传入namescriptalert(/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 的代码它只是提供一个修改密码的表单且所有参数走 GETURL 可见攻击者只需构造img srchttp://localhost/dvwa/vulnerabilities/csrf/?password_newhackpassword_confhack诱使管理员点击即可劫持会话。这才是教学意义——让你看清“无 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^LoginLogin: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 11无报错返回空结果原因MySQL 8.0 默认启用sql_modeONLY_FULL_GROUP_BY导致SELECT first_name, last_name FROM users WHERE user_id 1 or 11因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_modeSTRICT_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.1mysqli 会尝试 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) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;注意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 headtitleDVWA Attack Logs/title/head body h2Attack Logs (Last 100)/h2 table border1 trthID/ththTime/ththIP/ththModule/ththPayload/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 stylemax-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里埋点。不是为了炫技而是让学生明白——真实的攻防对抗中记录比攻击更重要。希望帮到你。本文还有配套的精品资源点击获取