DVWA存储型XSS实战:10分钟复现Cookie窃取与防御

📅 2026/7/28 5:13:20 👁️ 阅读次数 📝 编程学习
DVWA存储型XSS实战:10分钟复现Cookie窃取与防御

1. 项目概述:为什么存储型XSS是“潜伏的毒药”

在Web安全测试的实战演练中,DVWA(Damn Vulnerable Web Application)靶场几乎是每个安全从业者或爱好者的必经之路。它像一个精心设计的“漏洞博物馆”,将各种常见的安全问题集中呈现,供我们安全地学习和复现。今天我们要聚焦的,是其中一种极具威胁且容易被忽视的漏洞——存储型跨站脚本攻击。

存储型XSS,与反射型XSS最大的区别在于其“持久性”。反射型XSS的恶意脚本通常“一闪而过”,需要诱骗用户点击一个精心构造的链接;而存储型XSS则像一颗埋藏在服务器数据库里的“定时炸弹”。攻击者将恶意脚本提交到服务器(如留言板、用户资料、文章评论等),脚本被永久存储在数据库中。之后,任何访问到该内容的普通用户,其浏览器都会自动加载并执行这段恶意脚本。这意味着,一次成功的攻击,可以持续、自动地影响所有后续访问者,危害范围呈指数级扩大。

本次实战,我们将利用DVWA靶场的存储型XSS漏洞,完成两个经典目标:一是最直观的弹窗证明,二是更具危害性的Cookie窃取。整个过程力求在10分钟内清晰呈现,不仅让你看到漏洞现象,更要理解其背后的原理、利用手法以及防御思路。这不仅是复现一个漏洞,更是理解一种攻击思维,为构建更安全的Web应用打下基础。

2. 环境准备与靶场设置

2.1 DVWA靶场快速部署

DVWA的部署方式多样,对于想快速上手的同学,最推荐的是使用预配置的虚拟机或Docker镜像。这里以在Kali Linux或Parrot OS这类渗透测试发行版上使用Docker部署为例,因为它最干净、隔离性最好,避免污染本地环境。

首先,确保你的系统已经安装了Docker和Docker Compose。然后,创建一个简单的docker-compose.yml文件:

version: '3' services: dvwa: image: vulnerables/web-dvwa ports: - "80:80" restart: unless-stopped

保存文件后,在终端中进入该文件所在目录,执行命令docker-compose up -d。稍等片刻,Docker就会从仓库拉取镜像并启动容器。此时,在浏览器中访问http://你的服务器IP或localhost,就能看到DVWA的登录页面了。

注意:首次访问DVWA,页面可能会提示你需要运行一个安装脚本来配置数据库。点击“Create / Reset Database”按钮即可。完成后,使用默认账号admin和密码password登录。

2.2 关键安全等级设置

登录DVWA后,左侧菜单栏有一个非常重要的设置项:“DVWA Security”。点击进入,你会看到一个安全等级下拉菜单,包含“Impossible”、“High”、“Medium”、“Low”四个级别。

  • Impossible:几乎修复了所有漏洞,用于学习安全代码的写法。
  • High:存在漏洞,但加入了较强的过滤和防护机制。
  • Medium:存在漏洞,加入了一些基础的过滤(如大小写转换、字符串替换)。
  • Low:漏洞完全暴露,没有任何防护,最适合初学者理解漏洞本质。

为了本次10分钟速通实战,我们必须将安全等级设置为“Low”。这样,我们注入的恶意脚本才能不被过滤地存储和执行,让我们专注于攻击逻辑本身。请务必在开始前确认此项设置。

2.3 浏览器与调试工具准备

工欲善其事,必先利其器。一个合适的浏览器和其开发者工具是我们的“手术刀”。

  1. 浏览器选择:推荐使用Google ChromeMicrosoft Edge(Chromium内核)。它们内置的开发者工具功能强大且直观。
  2. 打开开发者工具:在浏览器页面按F12键即可打开。我们主要使用两个面板:
    • Console(控制台):用于查看JavaScript代码的输出、报错信息,也可以直接在这里执行JS代码进行测试。
    • Network(网络):用于监控浏览器发送的请求和接收的响应。在后续的Cookie窃取环节,我们可以在这里看到我们的“攻击服务器”是否收到了数据。
  3. 关闭不必要的浏览器扩展:某些广告拦截器或安全扩展可能会干扰我们的XSS Payload(攻击载荷)执行,建议在测试时使用浏览器的“无痕模式”或暂时禁用这些扩展。

环境就绪,靶场待命,接下来让我们直击核心,开始漏洞的挖掘与利用。

3. 存储型XSS漏洞原理深度拆解

在动手之前,我们必须搞清楚,存储型XSS这颗“毒药”是如何被酿造并发挥作用的。理解原理,才能举一反三,而不是死记硬背几个Payload。

3.1 漏洞产生的根本原因

存储型XSS漏洞产生的根源,可以归结为一个简单的安全原则被破坏:“不可信数据未经验证和净化就直接输出到网页上下文中”

我们来拆解一下DVWA(Low安全级别下)存储型XSS模块的典型数据流:

  1. 输入:用户在表单(比如“Name”和“Message”输入框)中提交数据。
  2. 传输:数据通过HTTP POST请求发送到服务器(例如dvwa/vulnerabilities/xss_s/)。
  3. 存储:服务器端PHP脚本(如xss_s.php未对输入内容进行任何过滤,直接将其插入SQL语句,保存到数据库中。
  4. 输出:当其他用户访问该页面时,服务器从数据库取出这条数据,未做任何转义处理,直接将其作为HTML代码的一部分,拼接进返回给浏览器的网页中。
  5. 执行:浏览器接收到HTML,将其解析为DOM。由于数据被当作HTML代码的一部分,其中的JavaScript代码(如<script>alert('XSS')</script>)就被浏览器当作合法的脚本指令执行了。

关键在于第3步和第4步。服务器既没有在存储前对输入进行“消毒”(Sanitization),比如过滤或转义特殊字符(<,>,&,",'等),也没有在输出时进行“转义”(Escaping),即将这些字符转换为它们的HTML实体(如<转成&lt;,>转成&gt;)。这使得用户输入能够“突破”数据区域的限制,升级为可以控制页面行为的代码。

3.2 与反射型、DOM型XSS的对比

为了更深刻理解存储型的特性,我们简单对比三种主要XSS类型:

类型触发方式数据存储位置影响范围典型场景
反射型XSS用户点击恶意链接不存储,在URL或POST数据中单个用户(点击者)搜索框错误提示、URL参数回显
存储型XSS访问存在恶意内容的页面服务器数据库所有访问该页面的用户论坛留言、用户昵称、博客评论
DOM型XSS用户与页面交互不存储,在客户端处理过程中单个用户前端JS操作URL片段(hash)、本地存储数据

从对比中可以看出,存储型XSS的危害性是最大的。攻击者只需要成功提交一次恶意代码,就可以实现“一劳永逸”的攻击效果,后续所有访问者都会在不知情的情况下“中招”,非常适合用于挂马、蠕虫传播和持久性的信息窃取。

3.3 DVWA漏洞点定位分析

在DVWA中,切换到“XSS (Stored)”页面。Low级别的页面通常包含一个简单的留言板。查看页面源代码,我们可以找到类似下面的表单:

<form name="XSS" action="#" method="POST"> <input type="text" name="txtName" placeholder="Your name"> <textarea name="mtxMessage" placeholder="Your message"></textarea> <input type="submit" name="btnSign" value="Sign Guestbook"> </form>

提交后,留言内容会显示在页面上方。通过浏览器开发者工具的“Elements”面板,查看显示留言的HTML结构,你会发现你的输入(比如名字和消息)被直接包裹在<div><td>标签内输出。例如:

<div id="guestbook_comments"> <p><strong>黑客</strong> 说:<br> 这是一条测试留言<script>alert(1)</script></p> </div>

这里,我们输入的<script>alert(1)</script>被原封不动地输出,浏览器解析时遇到了<script>开始标签,就会将其后的内容作为JavaScript代码执行。这就是最经典的漏洞点——数据被直接注入到了HTML正文中。

4. 实战复现一:基础弹窗验证

弹窗是证明XSS漏洞存在最直观、最经典的方式。它虽然不造成直接危害,但却是漏洞利用的“敲门砖”。

4.1 构造并注入Payload

  1. 访问DVWA的“XSS (Stored)”页面(安全等级已设为Low)。
  2. 在“Name”输入框中,可以输入任意名字,比如TestUser
  3. 在“Message”输入框中,输入我们的第一个Payload:
    <script>alert('XSS by YourName')</script>
    为了更具辨识度,可以将YourName替换为你自己的标识。
  4. 点击“Sign Guestbook”提交。

4.2 现象观察与原理验证

提交后,页面会刷新。如果一切正常,你会立即看到一个弹窗,内容正是“XSS by YourName”

此时,不要急着关闭弹窗。我们来做几个关键验证:

  1. 查看页面源代码:在浏览器中右键点击页面空白处,选择“查看页面源代码”。搜索你刚才输入的名字“TestUser”,你会看到类似这样的代码:

    <pre>Name: TestUser</pre> <pre>Message: <script>alert('XSS by YourName')</script></pre>

    看,我们的<script>标签被完整地写入到了HTML源码中。浏览器在解析这份源码时,遇到了<script>标签,就会执行其中的JavaScript代码,于是触发了alert函数。

  2. 验证持久性:关闭当前浏览器标签页,重新打开一个新的浏览器窗口,再次登录DVWA并访问“XSS (Stored)”页面。无需任何操作,弹窗会再次出现!这就是“存储型”的威力——恶意代码已经永久保存在服务器数据库里,每次页面加载都会从数据库读取并输出,导致弹窗反复执行。

实操心得:很多新手在这一步可能会失败,常见原因有两个。第一,DVWA的安全等级没有设置为“Low”。第二,某些浏览器的内置XSS过滤器(如Chrome的XSS Auditor,现已废弃,但部分机制仍存在)可能会拦截非常简单的Payload。如果遇到弹窗未出现,首先检查安全等级,其次可以尝试更复杂的Payload,如<img src=x onerror=alert(1)>,或者暂时关闭浏览器的安全防护进行测试。

4.3 绕过基础过滤的Payload思维

在“Medium”安全等级下,DVWA会尝试进行一些过滤。例如,它可能会使用str_replace(“<script>”, “”, $input)来尝试删除<script>标签。这时,我们的基础Payload就会失效。

如何绕过?思路是构造一个不会被简单字符串匹配删除的Payload

  • 大小写混淆<ScRiPt>alert(1)</sCrIpT>str_replace是大小写敏感的,它只找全小写的<script>
  • 嵌套标签<scr<script>ipt>alert(1)</script>。假设过滤逻辑是删除一次“