简介:DVWA是一款广受欢迎的开源Web安全靶场,面向网络攻防学习者、安全测试人员及CTF入门者,可用于练习SQL注入、XSS、文件上传等常见漏洞的利用与防护。整包共583个文件,以357个PHP核心源码文件为主,辅以HTML页面、JS/CSS前端资源以及TXT说明文档,压缩包仅1.29MB,配合phpstudy等集成环境即可快速部署。靶场采用经典Web应用结构,解压至网站根目录并修改数据库连接参数后,便能在浏览器中访问本地服务,省去手动搭建环境的繁琐步骤。资源目录清晰,附带配置说明与默认参数,便于新手对照源码理解漏洞成因,也可作为安全课程的教学实验平台。目前已有1504人学习下载,轻量易用,是一套不错的Web安全入门靶场环境。
DVWA靶场搭建与通关实战:从零开始搞懂Web漏洞
如果你正在学Web安全,却一直卡在“理论全会、实战全废”的阶段,那DVWA(Damn Vulnerable Web Application)应该是你绕不开的一个名字。这是一套自带各种漏洞的PHP Web应用,故意把自己写得浑身是洞,目的就是让安全学习者有一个合法、可控、不用提心吊胆的“练手沙盒”。我最早接触DVWA是为了准备一次内部安全培训,当时照着网上一堆零散教程搭环境,光卡在登录界面就折腾了一个晚上,后来踩完坑才发现,很多问题其实是版本、权限和PHP配置这些细节引起的,跟靶场本身没关系。
这篇东西我打算按自己实际操作的顺序来写:先讲清楚DVWA的核心设计逻辑,再分别给出Docker和原生LAMP两种搭建方案,然后是进入靶场之后必须做的初始化配置,接着挑几个高频漏洞模块做一次“带思路的通关演示”(重点覆盖SQL注入、XSS、CSRF和暴力破解),最后把新手最常遇到的几个故障排查场景整理成速查表。内容面向已经有一点Web基础、但还没真正动手搭过靶场的人,当然,如果你只是想找个地方练Burp Suite的抓包改包,这篇同样适用。
1. 先搞懂DVWA的设计逻辑,再动手搭建也不迟
很多新人拿到DVWA第一反应就是“赶紧装,装完赶紧打”,但我建议你先花十分钟搞清楚这套靶场到底是怎么设计的。你理解了它的结构之后,后面的搭建和通关都会顺畅很多。
1.1 一个“故意不设防”的Web应用到底怎么回事
DVWA本质上就是一个用PHP写的网站,有用户登录、数据库读写、文件上传、消息发布这些常见的Web功能模块。但它跟普通网站最大的区别在于:开发者故意用不安全的方式来实现这些功能——比如直接把用户输入拼进SQL查询、对输出完全不做转义、CSRF令牌形同虚设、验证码逻辑可直接绕过等。每个漏洞模块都对应一类经典Web安全风险,你在这个靶场里“打”进去,就等于把OWASP Top 10里那些高危漏洞挨个复现了一遍。
它内置了四个安全等级:Low、Medium、High、Impossible。每个等级对应同一功能模块的不同代码实现,Low等级几乎不设防,Medium和High会逐渐加入一些基础的防护手段,到了Impossible等级基本上就是安全的写法了。这里要特别强调一点:Impossible等级的代码是值得逐行去读的,它就是标准答案。我见过很多人在Low等级里打得风生水起,但问他“为什么这样能绕过”又说不清楚,其实最好的学习路径是Low打通之后,切到Impossible看一遍源码,把两种写法放在一起对比,防护逻辑一下就清晰了。
1.2 安全等级切换和Cookie的隐藏关系
DVWA的安全等级是通过一个叫dvwaSecurity的Cookie值来控制的,你切到某个等级,其实就是把这个Cookie的值改成low、medium、high或者impossible。这个机制本身也是个有趣的安全教学点——等级设置存在客户端,意味着用户可以自己改Cookie来切换等级,后面你在做CSRF和命令注入模块时,会频繁用到这个特性。
另外,DVWA每个等级之间不只是“过滤规则不同”,连漏洞的利用难度、需要的工具链都不一样。比如Low等级的SQL注入,直接手工在输入框里试就能出数据,但High等级的SQL注入是一个POST方式的JSON提交,你需要用Burp Suite或者写脚本才能愉快地玩。所以我的建议是:在一个等级里把每个模块过一遍,再切到下一个等级,而不是一次性把某个模块的四个等级全打完,这样你的攻击思维能保持连贯性。
2. 搭建方案选型:我为什么推荐用Docker而不是自己配LAMP
DVWA的搭建方式五花八门,常见的有三种:用Docker拉现成镜像、在Kali Linux里装LAMP环境然后部署源码、用Windows下的小皮面板(phpstudy)一键部署。我自己三种都试过,这里直接说结论:如果你只是个人学习用,首选Docker方案;如果你希望在靶场里做深度改造、加自定义漏洞,再考虑原生LAMP方案。
2.1 Docker方案的优势和两个靠谱镜像的选择逻辑
Docker方案最核心的优势是省事和干净。你不用手动去装Apache、MySQL、PHP,不用担心依赖版本冲突,一个docker-compose up就能把整套环境拉起来,不用了直接docker-compose down,不留任何垃圾在宿主机上。
Docker Hub上其实有多个DVWA镜像,但真正值得用的有两个:
sagikazarmark/dvwa:这个镜像把DVWA和MySQL打包在一起,也是DVWA官方README里推荐的Docker方式,更新频率比较稳定,我目前的主力环境就是这个。vulnerables/web-dvwa:老牌镜像,很多人早期教程用的都是它。但这个镜像比较旧,PHP版本停留在了5.x,而新版DVWA需要PHP 7.2+才能跑,所以如果你用的是这个镜像,大概率会出现页面能开、但初始化一直报错的怪问题。
所以如果你看到网上教程让你docker run -d -p 80:80 vulnerables/web-dvwa,还在纠结“怎么登录不了”,我建议直接换镜像。选镜像跟选工具一样,得先确认它有没有被维护,不是下载量高就一定适合。
2.2 Kali原生环境部署DVWA:适合想折腾底层的同学
如果你用的是Kali,或者想在本地Linux环境里完整走一遍“源码部署Web应用”的流程,那原生LAMP方案可以给你带来不少额外收获。你需要手动完成以下事情:
- 安装Apache、MySQL/MariaDB、PHP及必备扩展;
- 下载DVWA源码到Web根目录;
- 配置数据库连接文件
config/config.inc.php; - 设置
config/目录的写权限,方便初始化脚本自动创建配置文件; - 重启服务,访问
/setup.php完成数据库初始化。
这里有几个容易踩的坑,我逐个说:
- PHP版本不能太新也不能太旧。DVWA官方要求PHP 7.2以上,但Kali默认仓库里的PHP版本经常是8.x,而DVWA部分老版本模块在PHP 8下会报弃用警告甚至直接白屏。解决办法是更新DVWA源码到最新版,或者在PHP配置里把报错级别调低;如果你坚持用老版本DVWA,那需要手动装PHP 7.4。
allow_url_include必须开启。DVWA的File Inclusion模块需要PHP支持远程文件包含,这个选项默认是关闭的,需要在php.ini里打开,否则那个模块直接没法玩。- MySQL 8的认证插件坑。新版本MySQL默认用
caching_sha2_password认证,但旧版PHP的mysqli扩展不认识这个插件,会导致数据库连接失败,报错类似Unknown authentication method。解决方案是创建数据库用户时指定mysql_native_password,或者在装数据库时直接选MariaDB,后者基本没有这个问题。
原生方案能让你对Web应用运行的底层依赖有更具体的感知,比如PHP-FPM和Apache之间的关系、MySQL的权限体系、日志文件的查看方式等等。但如果你不是为了折腾,只是想赶紧进入漏洞练习阶段,Docker在时间和成功率上都是最优解。
3. 实操:用Docker在三分钟内把DVWA跑起来
下面是我的完整操作记录。我的环境是Ubuntu 22.04,安装好Docker Engine和Docker Compose插件后,一共就用了三条命令。
提示:如果你用的是带图形界面的Kali,建议在终端里执行命令时加上
sudo -i切换到root,避免后面频繁遇到权限问题。
3.1 下载并启动容器
首先创建项目目录,写一个docker-compose.yml:
version: "3" services: dvwa: image: sagikazarmark/dvwa:latest ports: - "8080:80" environment: - DB_HOST=mysql depends_on: - mysql mysql: image: mysql:8.0 restart: always environment: - MYSQL_ROOT_PASSWORD=root123 - MYSQL_DATABASE=dvwa然后在同目录下执行:
docker compose up -d第一次启动会拉镜像,需要等一会儿。启动完成后用docker ps确认两个容器都处于Up状态,然后浏览器访问http://localhost:8080。端口我特意映射成了8080,因为Kali自带的Apache经常占用80端口,没必要去跟它抢。
3.2 初始化数据库和账户
DVWA页面打开后会先跳转到登录页面,但如果你直接登录,它会提示数据库还没初始化。正确流程是:
- 访问
http://localhost:8080/setup.php; - 滚动页面,点击“Create / Reset Database”按钮;
- 系统会自动创建数据库表,并重置默认账户;
- 回到登录页,用默认账号
admin和密码password登录。
登录进去之后,你会看到一个类似后台的页面,左侧是菜单,右侧显示当前安全等级和PHP配置信息。到这里整套靶场就已经可用了。
这里有个细节值得说一下:setup.php页面里有个“PHP function allow_url_include: Disabled”的提示,如果你用Docker镜像,它一般已经帮你开好了;但如果是原生部署,你需要在php.ini里手动开启这个选项。还有一个常见现象是,点击“Create/Reset Database”后一直转圈,多半是数据库容器没起来,用docker compose logs mysql看看日志,基本就能定位问题。
3.3 登录进去之后,先检查这三个配置
成功登录并完成数据库初始化后,先不要急着去打靶,建议先把环境确认一遍:
- 安全等级:右上角或
DVWA Security菜单里可以切换等级。建议刚开始把所有模块的等级调到Low,先熟悉漏洞的触发和利用流程,再逐步提高。 - PHP版本和函数限制:在
PHP Information页面里看disable_functions,如果exec、system被禁用,命令注入和文件包含这两个模块在High以上等级会打不通。 - 目录权限:如果
File Upload模块上传后找不到文件,检查hackable/uploads/目录的写权限;Docker镜像一般没问题,原生部署容易漏这一步。
4. 靶场通关实操:从Brute Force到XSS的几个核心思路
DVWA一共十几个模块,但新手拿到手最容易陷进去的是暴力破解和SQL注入。这两个模块也是最容易让新人产生“我是不是会渗透了”的错觉的地方。我在这节里挑四个代表性模块,讲讲它们的做题思路和工具配合方式。
4.1 Brute Force模块:Burp Suite的第一次亲密接触
Low等级的Brute Force就是一个简单的登录表单,没有验证码、没有次数限制,你可以在输入框里直接猜弱口令,也可以用Burp Suite抓包后做字典爆破。
实际操作中我更推荐用Burp Suite的Intruder功能,因为这样能练到工具配合的完整链路。流程如下:
- 打开Burp Suite,Proxy确认拦截开关打开;
- 浏览器访问DVWA的Brute Force页面,随便输入一组账号密码登录,Burp会抓到包含
username和password参数的GET请求; - 把请求发送到Intruder(快捷键Ctrl+I);
- 对
username和password参数分别标记为Payload位置; - 选择Payload类型为“Simple list”,填入常见弱口令字典;
- 设置Payload处理规则(比如用户名和密码的排列组合),点击Start Attack。
High等级的Brute Force有一个很有代表性的反爬机制:使用了Anti-CSRF Token,每个请求都会带一个动态变化的user_token,如果你直接用Burp Intruder去爆破,会因为Token失效而全部失败。这个问题的解法有两个方向:
- 用Burp Suite的“Recursive Grep”或写一个Python脚本,先从响应中提取Token,再带着新Token发下一次请求;
- 或者换个思路:既然Token是存在Session里的,能不能绕过Token检测,直接复用会话?实际操作里并不总是能成功,因为High等级每次请求都会校验Token,而Token值藏在响应体里。因此最优雅的方案还是写一个自动化脚本,用
requests库维护Session,每次请求前用正则从响应中提取Token。
这个过程其实非常锻炼人,做一次爆破脚本,你对Session管理、正则提取、HTTP状态码的理解都会上一个台阶。
4.2 SQL Injection模块:从手工注入到sqlmap辅助
Low等级的SQL注入把用户输入直接拼进了SQL语句:
SELECT first_name, last_name FROM users WHERE user_id = '$id';你输入1' OR '1'='1,相当于查询user_id = '1' OR '1'='1',直接绕过条件限制,返回全部用户。这是最基础的字符型注入,你可以先在输入框里试试1'-- -和1' OR 1=1-- -,再配合Union查询去探测字段数量和数据表结构。
这里不建议一上来就用sqlmap,因为手工注入能帮你建立“注入到底是什么”的直觉——比如判断注入点、猜字段数、找回显位、爆库名、爆表名、爆字段、拿数据,这个链路跑通一遍,你对SQL执行逻辑的理解会强很多。等手工能稳定走通,再用sqlmap -u "url" --cookie "PHPSESSID=xxx" --dbs去体验一下自动化,你会发现sqlmap的原理其实就是把你手工做的事自动化了,这样你能更理性地看待工具。
Medium和High等级会分别加入mysqli_real_escape_string和intval这类防护,但不是每个参数都覆盖到了,所以仍然存在绕过空间。我特意提醒一下:在DVWA的SQL Injection模块里,虽然叫SQL注入,但测试目标不只有数字型和字符型,High等级是个POST提交的JSON数据,参数传递方式不同,注入点的构造方式也不同。
4.3 XSS模块:反射型、存储型和DOM型的区别
DVWA的XSS模块分成三种:Reflected(反射型)、Stored(存储型)和DOM Based(DOM型)。很多新人打完一遍还是分不清三者的区别,我提供一个最简单的判断标准:
- 反射型:你输入的Payload会被拼进响应当中,但只影响当前请求的响应,不会写入数据库。也就是“你自己打自己”;
- 存储型:Payload被保存到数据库中,下次任何用户访问这个页面时都会触发。也就是“你打所有访问者”;
- DOM型:Payload不会出现在初始HTML里,但会被前端的JavaScript读取并写入到页面中。
Low等级的三个XSS模块都很好打,直接在输入框里提交<script>alert(1)</script>就能看到弹窗。Medium开始有基础的过滤,比如把<script>替换成空字符串,但不做递归过滤,所以用<scr<script>ipt>就能绕过;High等级则会使用preg_replace配合正则去删除某些危险标签,这种级别的过滤只能通过事件属性等更隐蔽的方式来尝试绕过。
对于一个学习者来说,XSS模块最关键的是养成观察“哪里是输出点”的习惯。前端渲染、后端拼接、URL参数、document.write、innerHTML赋值,这些都是XSS的落脚点,而它们对应的绕过逻辑是完全不同的。
4.4 CSRF模块:理解请求伪造的“借刀杀人”
CSRF模块在DVWA里做得非常直观。Low等级里,攻击者只需要构造一个恶意链接,诱导受害者点击,就能在受害者不知情的情况下修改密码。你可以先在DVWA里修改一次密码,然后用Burp拦截请求,把请求改造成一个假页面,页面上放一个<img>标签,src指向DVWA的密码修改URL,当受害者浏览器加载这个页面时,就会自动发出那个修改密码的请求。
Medium等级加入了HTTP_REFERER校验,它要求请求来源必须是同一个域名。看起来比Low安全,但很多开发者对REFERER的理解并不深入——校验逻辑往往是“判断Referer里是否包含hostname”,而不是“是否等于hostname”,这就是一个可以绕过的点。你可以试试在恶意页面里加上一个指向目标的链接,或者在Referer里伪造部分信息,看看能不能骗过服务器。
High等级则加入了Anti-CSRF Token,这时候靠单纯的“诱导点击”已经不行了,因为攻击者无法提前获取到合法的Token。对这个等级我的建议不是“如何突破”,而是你应该反过来想:Token防住了CSRF,但它为什么防不住XSS?想明白这个问题,你对跨站攻击和跨站请求伪造的理解就会连成一片。
5. 高频故障排查:进不去登录界面、数据库报错、docker权限问题
这部分是很多人最容易卡住的地方。我整理了一份自己的“踩坑速查表”,按症状、可能原因、解决方案三列排列,你可以直接对照排查。
| 症状 | 可能原因 | 解决方案 |
|---|---|---|
访问http://localhost:8080一直转圈或连接被拒绝 | 容器没起来或端口映射冲突 | 执行docker compose ps确认容器状态;查看宿主机8080端口是否被占用,尝试改映射端口 |
能打开页面,但登录时提示Can not connect to MySQL server | 数据库容器没有连上,或数据库配置不对 | 检查docker compose logs mysql日志;确认config.inc.php中的数据库地址是容器名mysql而不是localhost |
| 点击Create/Reset Database后一直在转圈 | 数据库初始化超时,通常是容器内存或权限问题 | 重启docker compose restart mysql,然后重新访问setup.php再点一次 |
| 页面能进但所有样式都乱了 | 静态资源路径不对,通常是没在根目录部署 | Docker镜像一般不会出现,原生部署检查Apache的DocumentRoot配置和目标目录结构 |
| 上传图片后访问404 | 上传目录不存在或没权限 | 创建hackable/uploads/目录并赋chmod 777权限,重点检查SELinux是否拦截 |
| 一些模块(如Command Injection)页面就报500或直接空白 | PHPexec函数被禁用,或PHP版本过新 | 检查disable_functions配置,去掉exec、system等函数;换用最新版DVWA或将PHP降到7.4 |
这些坑里,我最想单独提醒的是“Docker方式部署后无法进入登录界面”这个问题。它其实是两个独立现象混在一起了:一个是容器没起来,另一个是数据库没初始化成功。前者检查端口和容器状态,后者看一下setup.php页面的提示。如果你在浏览器输入地址后看到的是Apache默认页面而不是DVWA登录页,多半是端口没映射对——你访问的是宿主机上另一个服务的80端口,或者Docker映射端口和访问地址没对上。
6. 针对标题里的“zip”包:解压后需要确认的几件事
如果你手头拿到的是一份叫“DVWA-网络安全靶场.zip”的压缩包,而不是通过Docker拉镜像部署的,那说明你走的应该是原生部署路线。解压之后先别急着复制到Web目录,先确认这三件事:
- 压缩包里的源码版本。看
DVWA目录下有没有composer.json或CHANGELOG文件,确认它不是十年前的远古版本。老版本代码在新PHP环境上兼容性很差,就算启动成功,很多模块也会因为函数变更直接报错。 - 数据库初始化文件是否完整。DVWA的库表结构是通过
setup.php动态创建的,源码包里一般不会直接带.sql文件。如果你的压缩包里直接提到了“导入数据库”,你要小心这个包是不是被第三方改过,优先从官方渠道获取最新源码才是稳妥做法。 - 默认配置文件是否存在。解压后的
config目录里应该有一个config.inc.php.dist文件,你需要复制一份并重命名为config.inc.php,再修改其中的数据库账号密码才能连上数据库。
老实说,从压缩包部署DVWA的方法绕了一圈反而容易遇到各种兼容性问题。除非你是离线环境、完全没办法用Docker拉取镜像,否则我依然推荐容器方案,省时省力,且环境和官方一致,后续排查问题时社区更有可能遇到同样的情况。
写在最后
我自己的体会是,DVWA最大的价值不是“打穿”,而是让你在同一个漏洞面前反复横跳,拿四种不同等级的代码做对比,理解为什么一份看起来差不多的代码,换一个过滤函数、加一个Token校验,攻击难度就完全不同。这种对比思维,比你会用十个工具都重要。
最后分享一个小技巧:你每次打完一个模块,可以顺手把Payload、绕过思路和一个关键截图存到一个笔记里,最后整理成自己的Web漏洞checklist。等以后你去测真实目标时,这套从DVWA里练出来的肌肉记忆会帮你少走很多弯路。
本文还有配套的精品资源,点击获取