DVWA靶场实战指南:从环境搭建到Web漏洞修复全解析

发布时间:2026/10/22 16:44:41
DVWA靶场实战指南:从环境搭建到Web漏洞修复全解析 聊到Web安全入门DVWA基本是绕不开的第一站。它是部署在本地的“漏洞练习沙盒”内置了SQL注入、XSS、CSRF、命令注入、文件上传等一整套经典漏洞场景专门给学习者创造一个可以放心动手的实验环境。我接触过的很多搞安全的同行包括带过的几个新人最开始都是在DVWA上把每个漏洞点亲手打一遍、把修复代码读一遍才真正建立起对Web漏洞的“体感”。这篇文章就把我在DVWA实战里的完整思路和踩坑记录梳理一遍从环境部署到模块拆解再到常见故障排查尽量讲透为什么这么做、注意什么给后来的学习者一条少走弯路的参考路径。1. 靶场认知与环境准备1.1 DVWA是什么以及为什么拿它练手DVWA全称Damn Vulnerable Web Application翻译过来就是“设计得过于脆弱的Web应用”。它本质上是一个照着真实业务逻辑写出来的“负样本工程”——有用户登录、有CURD操作、有上传下载、有会话机制但每一个功能点都刻意留下了经典漏洞。和真实系统唯一的关键区别是它是给你打来练习用的所有攻击演示在本地环境自生自灭不会影响到任何真实用户和数据。我自己的体会是DVWA最大的价值在于它同时提供了“攻击视角”和“防御视角”。每个模块都有PHP源码可直接查看你可以看到漏洞形成的代码原因也能看到不同安全级别下防御代码的差异。很多新手在真实渗透测试里最容易犯的毛病就是“跑完扫描器不知道发生了什么”在DVWA里这个问题基本不存在——打穿一个漏洞之后直接打开源代码漏洞原理一目了然。这种“先打击后复盘”的循环才是建立起漏洞直觉最快的路径。适合拿DVWA练手的人群挺明确的刚学Web安全的初学者、准备面试安全岗位的应届生、负责Web开发的程序员想理解攻击原理都适合。它不要求你有多深的基础PHP语法懂一点更好不懂也不妨碍理解漏洞逻辑。1.2 环境搭建与数据库初始化部署DVWA有两条主流路线集成环境手动部署以及容器化一键启动。手动部署的典型组合是Apache/Nginx PHP MySQL。PHP版本建议5.6到7.4之间太高版本可能因为函数废弃导致部分模块报错MySQL/MariaDB选5.x或8.x都行。把DVWA源码解压放到网站根目录重命名为dvwa访问http://127.0.0.1/dvwa就能进入安装引导。初始化时它会要求配置数据库位置在config/config.inc.php。核心配置项是数据库地址、用户名、密码和库名$_DVWA[ db_server ] 127.0.0.1; $_DVWA[ db_database ] dvwa; $_DVWA[ db_user ] root; $_DVWA[ db_password ] 你的密码; $_DVWA[ db_port ] 3306;改完配置后点击页面上的“Create/Reset Database”按钮它会自动建库建表并写入初始数据。这一步完成以后默认账号admin/password就能登录了。这里有个常见坑如果点完按钮页面一直卡在白色或提示无法连接数据库九成是config.inc.php里的密码写错或者MySQL服务没启动。另外config/目录在线上部署时必须要限制访问config.inc.php里有明文数据库口令这个习惯要从靶场阶段就养成。容器化部署相对省心一条命令能把环境跑起来。DVWA官方维护了Docker镜像用的组合一般是ApachePHPMariaDB一体。容器方式的好处是打坏了直接删掉重建恢复成本几乎为零适合高频练习。我个人建议学习期用集成环境手动部署一次过程中会逼着你接触PHP运行环境、数据库连接、权限目录这些真实部署知识这些坑在容器里都被隐藏掉了。2. 模块功能与难度分级解读2.1 四档难度到底差在哪DVWA页面右上角可以切换安全级别Low、Medium、High、Impossible。这四档不是简单调参数而是直接对应四种截然不同的代码写法。Low级别的代码是“裸奔”状态SQL查询直接拼接用户输入前端也没有任何过滤连最基本的安全意识都没有。Medium级别增加了一些基础防御手段比如用mysql_real_escape_string()转义用户输入或者对上传文件限制Content-Type类型听上去像个样子了但实际都能被绕过——比如转义不等于参数化枚举黑白名单总会漏。High级别就开始上“正经防御”了比如SQL查询用预编译绑定参数、文件上传校验文件内容头部、CSRF校验Token遇到这类防御常规脚本打法已经很难奏效需要结合业务逻辑找漏洞。Impossible级别基本上就是“修复完的基准答案”不仅参数化查询还会加二次确认、随机Token、服务端校验等。我建议练法是从Low开始先把每个漏洞的利用流程跑通再对比Medium和High的防御代码琢磨“这段代码为什么可以被绕过”最后打开Impossible源码看看生产级修复长什么样。这一步对写自己代码的安全意识提升非常明显。2.2 模块清单与真实风险对应DVWA默认内置了十几个测试模块每个模块都对应开发实践中真实出现过的风险点这里先给个整体地图后面再逐个拆实战模块对应漏洞类型真实世界的典型场景SQL Injection注入攻击登录框、搜索框被拼SQL获取全库XSS (Reflected/Stored/DOM)前端脚本注入论坛评论、搜索回显区被恶意脚本抢占Command Injection命令注入Ping工具、调系统命令的业务接口被追加系统命令CSRF跨站请求伪造诱导登录用户在不知情下改密码、转账File Upload文件上传绕过头像上传功能被传WebShellFile Inclusion文件包含动态加载页面参数被篡改为本地/远程文件Brute Force暴力破解登录接口无频率限制可被批量猜测Insecure CAPTCHA验证码逻辑绕过验证码只校验第一步或返回参数可控Weak Session ID会话可预测会话ID可被猜测导致身份伪造每个模块都建议至少打两轮第一轮不管防御代码先体验利用过程第二轮开源码看修复差异。两轮下来才算真正“消化”了这个漏洞点。3. 核心模块实战拆解3.1 SQL注入从探测到脱库的完整链路SQL注入是DVWA里最值得反复练的模块。Low级别的注入点在一个用户查询接口输入用户ID就返回对应信息。手动探测经典路径如下。先用单引号改变SQL语句结构。输入1如果页面报错或返回异常说明查询语句结构被破坏了存在注入可能。接着判断字段数用ORDER BY逐级试探1 ORDER BY 1 -- 1 ORDER BY 2 -- 1 ORDER BY 3 --MySQL数据库下--后面要带一个空格表示注释掉剩余SQLDVWA里如果注释没加空格经常会报语法错误这是新手最容易卡住的位置之一。当ORDER BY N正常而N1报错时N就是查询的字段总数。这个模块固定是2个字段所以到1 ORDER BY 3 --时报错。字段数确定后要用UNION SELECT找回显位置1 UNION SELECT 1,2 --页面某处显示出数字1或2那个位置就是数据可以回显的区域。接下来把数字换成数据库函数就能直接拖数据了1 UNION SELECT database(),user() -- 1 UNION SELECT version(),datadir --看到当前库名之后查表名、字段名、字段内容就是下半场。表名查询1 UNION SELECT table_name,table_schema FROM information_schema.tables WHERE table_schemadvwa --拿到表名如users再查字段1 UNION SELECT column_name,column_type FROM information_schema.columns WHERE table_nameusers --最后一步拖出用户和密码哈希1 UNION SELECT user,password FROM users --Low级别的接口就这么几行全穿了。整个过程中最有价值的复盘点不是“我注入了”而是观察代码。打开源码看底层拼接逻辑你会看到类似$query SELECT first_name, last_name FROM users WHERE user_id $id;这样的语句任何用户输入都会被直接嵌入SQL字符串——这才是漏洞根源。Medium级别的源码会在查询前对输入加一层mysqli_real_escape_string()转义。这种转义能处理单引号、双引号等特殊字符但对数字型注入几乎无效——因为参数不带单引号包裹时注入载荷完全不需要引号。Medium界面提供下拉框选择ID但Burp抓包改成1 UNION SELECT user,password FROM users照样能打原因就是前端限制不是安全限制。High级别实际防御已经比较到位了把查询改成预编译的预处理语句$stmt $db-prepare( SELECT first_name, last_name FROM users WHERE user_id ? ); $stmt-bind_param( s, $id );参数值被当作数据而不是SQL代码传给数据库引擎注入载荷就没有执行空间了。看这段代码就能彻底明白为什么预编译是SQL注入的标准解药而不是“过滤敏感字符”。我在实操中还会补充一个习惯每次做完注入练习把回显的数据截图留档把使用的Payload和原理写在测试笔记里这种记录习惯对面试复盘非常有用。3.2 XSS三兄弟反射、存储、DOM的区别与利用XSS模块在DVWA里被拆成三个独立练习分别是反射型、存储型和DOM型。同样是执行前端恶意脚本三者触发机制完全不同别混为一谈。反射型XSS的触发路径是“把输入原样反射到当前页面”。Low级别的反射型XSS直接在一个输入框提交后把内容嵌入页面输入scriptalert(document.cookie)/script刷新后弹窗。这类XSS之所以叫“反射型”是因为恶意脚本不做持久化而是藏在URL参数里诱导目标用户点击。要理解它的杀伤力可以模拟一个钓鱼场景构造一个看似正常的链接把参数值换成恶意脚本发给登录该应用的用户脚本在目标浏览器上下文里执行可以读取当前站点的Cookie。存储型XSS更危险脚本被持久化到数据库里任何访问该页面的用户都会触发。DVWA里有个类似留言板的模块我提交scriptalert(document.cookie)/script后刷新页面每次都会弹窗。因为服务端只是把留言内容存库页面渲染时又原样输出了HTML标签。真实世界的论坛、评论区一旦存在这类漏洞恶意代码可以长期驻留影响所有浏览用户。存储型XSS练完后建议顺手把恶意的script包在img onerror、svg onload等不同标签里都测一遍因为很多过滤正则只盯着script关键字却漏了其他可执行事件。DOM型XSS的特别之处在于“服务端完全不知道发生了什么”。它的漏洞出现在前端JavaScript处理URL、hash或DOM属性时。DVWA的DOM型页面会读取URL中的参数然后用document.write或innerHTML把它写进页面。我在地址栏构造?defaultscriptalert(1)/script脚本在页面本地逻辑里被执行网络请求里看不到任何恶意痕迹。这也是为什么DOM XSS更难被服务端WAF拦截。难度升级方面Medium会给反射型XSS加正则过滤script但双写scrscriptipt绕过成功率很高因为过滤只处理了一遍High的过滤正则开始针对所有HTML标签做黑白名单判断普通脚本确实进不去了但像img srcx onerroralert(1)这种历史经典载荷仍然可能存活。存储型XSS在High级别过滤链路完善后会难打很多但DOM型一直打到High都可能有突破口——因为服务端过滤管不到纯前端触发的注入。防御段源码值得认真读Impossible级别不仅用htmlspecialchars()把HTML字符实体化还在输出前做了编码处理。简单说用户输入是“数据”还是“代码”取决定输时的转义处理这个认知比背几个绕过Payload有用得多。3.3 命令注入一个分号打穿系统命令注入模块模拟的是一个类似“Ping检测”的工具输入一个IP后端调用系统Ping命令并回显结果。我刚开始练这个模块时第一反应是“这有什么可研究的”直到我在输入框里填入127.0.0.1; whoami发现页面直接回显了当前系统用户名——那一刻才意识到系统命令一旦被拼进命令行有多致命。Low级别的代码长这样$target $_REQUEST[ ip ]; $cmd shell_exec( ping -c 3 . $target );这里没有任何过滤处理用户输入被直接追加到系统命令后面。分号;在Linux shell中表示“前面命令执行完了继续执行后面的命令”于是ping -c 3 127.0.0.1; whoami实际执行了两条命令。类似的连接符还有、||、管道|和反引号比如利用管道读取文件127.0.0.1 | cat /etc/passwdMedium级别源码开始对分号和做黑名单过滤但黑名单总有漏网之鱼管道符没被处理所以用管道符依旧可以执行后续命令。High级别防御升级到按空格、分号和关键系统命令字过滤听着挺全但Linux下可以用$IFS$9代替空格来绕过关键字限制比如构造127.0.0.1$IFS$9;cat$IFS$9/etc/passwd。这些“绕过思路”的价值不在于背命令而在于理解黑名单防御的本质缺陷你永远不可能枚举完所有可能的输入变体。Impossible级别的修复方案就转向了白名单思路先把输入转换成长整型然后校验IP地址格式$target $_REQUEST[ ip ]; $ip ip2long( $target ); // 转为整数 if ( $ip ! false ) { $cmd shell_exec( ping -c 3 . long2ip( $ip ) ); }输入从源头上被限制在这个业务真正需要的格式里不存在携载其他命令的空间。这种“白名单校验输入格式”的思路其实贯穿所有安全修复也是我最推荐读者在源码里反复体会的一点。3.4 CSRF改密码的陷阱与防护CSRF是很多新手觉得“没什么大不了”的漏洞但它恰恰是所有依赖Cookie鉴权的Web应用最容易中招的问题。原理简单说目标用户在目标站点处于登录状态浏览器自动携带Cookie发起请求攻击者只要诱导用户在另一个页面发出构造好的请求目标站点就会误以为是用户本人在操作。DVWA的CSRF模块是一个密码修改功能。Low级别下修改密码的请求是GET方式接口长这样GET /dvwa/vulnerabilities/csrf/?password_new123456password_conf123456ChangeChange我用Burp抓到这条请求后直接在本地搭一个恶意页面img srchttp://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new123456password_conf123456ChangeChange只要已登录用户浏览器加载这个页面浏览器就会带着目标站点的Cookie发起这次GET请求密码就被静默修改了。整个过程用户毫无感知除非他后来尝试用旧密码登录才发现异常。Medium级别把GET改成了POST但这并没有根本解决问题——攻击者可以构造隐藏表单加JavaScript自动提交照样实现跨站请求。真正有效的是High和Impossible级别的防护在表单里加入一个随机的不可预测的CSRF Token服务端校验请求中携带的Token是否匹配当前会话才能通过修改。因为Token是每次会话动态生成的攻击者无法提前预知也就无法构造有效请求。这个模块练完后我建议回头看一下你们自己的业务代码凡是涉及修改密码、绑定手机、转账等敏感操作的接口如果没有同步校验Token或同源头就有同样的风险窗口。靶场里打一次构造恶意页面的过程比读十篇CSRF科普文章都直观。3.5 文件上传前端校验是纸糊的墙文件上传模块模拟的是头像上传功能在真实业务里这几乎是最快被“打穿”的功能点之一。Low级别没有任何有效防御上传一个shell.php里面写入最基础的PHP探针代码访问上传路径就能在靶场里看到代码被执行。整个流程零阻碍但复盘时看点在于为什么“上传脚本文件”是危险的因为Web服务器把PHP文件交给PHP解释器执行攻击者上传的代码就和站点自身代码拥有同等的执行权限。Medium级别开始有校验了但校验的是Content-Type和文件后缀黑名单。前端可绕过Burp拦截上传请求后把Content-Type从text/php改成image/png即可。更值得研究的是High级别的黑名单拦截它检查了.php、.php3、.phtml等一大批后缀却有可能漏掉一些环境默认可执行的畸形后缀。而且黑名单永远面临“命名变体”的难题这也是为什么生产环境推荐白名单存储目录禁止执行脚本权限的方案。XSS、内容检测、双扩展名和大小写绕过这些思路在这个模块里都能用一用。比如上传一个.phtml或.php.jpg或者用十六进制编辑器在图片尾部拼接PHP代码构造所谓的“图片马”。用代码审计视角看Impossible级别源码它做了三件事校验MIME类型、校验文件头魔数、限制扩展名白名单。这套组合拳基本堵死了常见的脚本文件伪装手段。安全提醒必须在这里多说一句所有上传的“WebShell”只允许在本地DVWA靶场环境里运行任何情况下都不要把这类文件传到真实服务器或测试他人系统这种行为已经超出学习边界可能涉及违法。学攻击是为了理解防御不是为了实施破坏。3.6 文件包含与暴力破解的补充分析文件包含模块在DVWA里体现为动态加载文件。Low级别的漏洞点是页面直接拼接用户参数作为包含路径传入../../../../etc/passwd这样的路径就能读取系统文件。这里建议同步练习PHP封装协议用php://filter读取源码文件例如php://filter/readconvert.base64-encode/resource../index.php拿到base64编码后解码就能看到服务端源码。这个技巧在CTF里非常高频也是理解“动态包含”危险性的钥匙。High级别开启了allow_url_include限制并增加文件路径前缀检查难度上去了但配套的代码审计思路也更接近生产环境的防御设计。暴力破解模块本质是登录接口无频率限制。Low级别可以手动把Burp的拦截代理打开用抓包工具重放登录请求把密码字段做成字典跑批。这里顺便提一个新手常犯错误直接在浏览器手工猜密码练完根本看不出漏洞特征。正确做法是利用抓包工具设置一个Payload字典观察不同密码在响应长度上的差异锁定正确的密码。Medium/High级别开始引入登录失败锁定和Token机制但有些版本存在逻辑漏洞Token在失败后没有更新又可以重复提交这个“刷新Token”的细节也值得记进实验笔记。4. 常见故障与排查实录4.1 环境层面的高频问题白屏和数据库连接失败是新手反馈最多的两个问题。页面能打开但点初始化按钮后空白先检查PHP错误日志比较典型的原因是mysqli扩展未启用或者PHP版本高于7.4导致某些老函数废弃直接抛Fatal error。数据库连接失败优先看config.inc.php里的账号密码是否和服务端一致其次是MySQL服务有没有起来最后再排查端口被占用。难度切不了也很常见。DVWA的难度选择写入config/config.inc.php里的$_DVWA[default_security_level]变量改了之后需要清Cookie再刷新才会生效。如果页面反复跳到登录页同样是Cookie问题。4.2 攻击链路打不通怎么定位SQL注入拿到单引号报错但UNION SELECT一直不出数据原因基本是字段数猜错了或者注释符后面缺了空格。建议把ORDER BY探测和注释符空格固定成条件反射。XSS弹不出窗先看浏览器是否拦截了alert()——现代浏览器对alert有频率限制练习时可以换成console.log(document.cookie)或print()。存储型XSS刚提交不弹先刷新一次页面再看因为脚本是随页面后续访问才执行的。文件上传后访问报404先确认上传目录的绝对路径和文件是否真的写入磁盘有时候是文件名被重写了。4.3 防御优先的思维习惯最后说一个我测完所有模块后最深的体会不要把DVWA当成“攻击工具箱”它最值钱的部分是配对的修复代码。把每个漏洞在Impossible级别下的修复方案读懂你的收获会远超能背多少Payload。而且务必在本地环境结束一切测试不要顺手把这些Payload搬到别人的网站上验证网络安全领域最忌讳的就是把学到的技术用错地方。我在后续练其他靶场时一直保持着“先打穿再读修复再总结”的三步节奏这套方法论确实帮我在真实业务代码里更敏锐地看出问题接口。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询