DVWA存储型XSS实战:10分钟复现Cookie窃取与防御 1. 项目概述为什么存储型XSS是“潜伏的毒药”在Web安全测试的实战演练中DVWADamn 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 浏览器与调试工具准备工欲善其事必先利其器。一个合适的浏览器和其开发者工具是我们的“手术刀”。浏览器选择推荐使用Google Chrome或Microsoft EdgeChromium内核。它们内置的开发者工具功能强大且直观。打开开发者工具在浏览器页面按F12键即可打开。我们主要使用两个面板Console控制台用于查看JavaScript代码的输出、报错信息也可以直接在这里执行JS代码进行测试。Network网络用于监控浏览器发送的请求和接收的响应。在后续的Cookie窃取环节我们可以在这里看到我们的“攻击服务器”是否收到了数据。关闭不必要的浏览器扩展某些广告拦截器或安全扩展可能会干扰我们的XSS Payload攻击载荷执行建议在测试时使用浏览器的“无痕模式”或暂时禁用这些扩展。环境就绪靶场待命接下来让我们直击核心开始漏洞的挖掘与利用。3. 存储型XSS漏洞原理深度拆解在动手之前我们必须搞清楚存储型XSS这颗“毒药”是如何被酿造并发挥作用的。理解原理才能举一反三而不是死记硬背几个Payload。3.1 漏洞产生的根本原因存储型XSS漏洞产生的根源可以归结为一个简单的安全原则被破坏“不可信数据未经验证和净化就直接输出到网页上下文中”。我们来拆解一下DVWALow安全级别下存储型XSS模块的典型数据流输入用户在表单比如“Name”和“Message”输入框中提交数据。传输数据通过HTTP POST请求发送到服务器例如dvwa/vulnerabilities/xss_s/。存储服务器端PHP脚本如xss_s.php未对输入内容进行任何过滤直接将其插入SQL语句保存到数据库中。输出当其他用户访问该页面时服务器从数据库取出这条数据未做任何转义处理直接将其作为HTML代码的一部分拼接进返回给浏览器的网页中。执行浏览器接收到HTML将其解析为DOM。由于数据被当作HTML代码的一部分其中的JavaScript代码如scriptalert(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 nameXSS action# methodPOST input typetext nametxtName placeholderYour name textarea namemtxMessage placeholderYour message/textarea input typesubmit namebtnSign valueSign Guestbook /form提交后留言内容会显示在页面上方。通过浏览器开发者工具的“Elements”面板查看显示留言的HTML结构你会发现你的输入比如名字和消息被直接包裹在div或td标签内输出。例如div idguestbook_comments pstrong黑客/strong 说br 这是一条测试留言scriptalert(1)/script/p /div这里我们输入的scriptalert(1)/script被原封不动地输出浏览器解析时遇到了script开始标签就会将其后的内容作为JavaScript代码执行。这就是最经典的漏洞点——数据被直接注入到了HTML正文中。4. 实战复现一基础弹窗验证弹窗是证明XSS漏洞存在最直观、最经典的方式。它虽然不造成直接危害但却是漏洞利用的“敲门砖”。4.1 构造并注入Payload访问DVWA的“XSS (Stored)”页面安全等级已设为Low。在“Name”输入框中可以输入任意名字比如TestUser。在“Message”输入框中输入我们的第一个Payloadscriptalert(XSS by YourName)/script为了更具辨识度可以将YourName替换为你自己的标识。点击“Sign Guestbook”提交。4.2 现象观察与原理验证提交后页面会刷新。如果一切正常你会立即看到一个弹窗内容正是“XSS by YourName”。此时不要急着关闭弹窗。我们来做几个关键验证查看页面源代码在浏览器中右键点击页面空白处选择“查看页面源代码”。搜索你刚才输入的名字“TestUser”你会看到类似这样的代码preName: TestUser/pre preMessage: scriptalert(XSS by YourName)/script/pre看我们的script标签被完整地写入到了HTML源码中。浏览器在解析这份源码时遇到了script标签就会执行其中的JavaScript代码于是触发了alert函数。验证持久性关闭当前浏览器标签页重新打开一个新的浏览器窗口再次登录DVWA并访问“XSS (Stored)”页面。无需任何操作弹窗会再次出现这就是“存储型”的威力——恶意代码已经永久保存在服务器数据库里每次页面加载都会从数据库读取并输出导致弹窗反复执行。实操心得很多新手在这一步可能会失败常见原因有两个。第一DVWA的安全等级没有设置为“Low”。第二某些浏览器的内置XSS过滤器如Chrome的XSS Auditor现已废弃但部分机制仍存在可能会拦截非常简单的Payload。如果遇到弹窗未出现首先检查安全等级其次可以尝试更复杂的Payload如img srcx onerroralert(1)或者暂时关闭浏览器的安全防护进行测试。4.3 绕过基础过滤的Payload思维在“Medium”安全等级下DVWA会尝试进行一些过滤。例如它可能会使用str_replace(“script”, “”, $input)来尝试删除script标签。这时我们的基础Payload就会失效。如何绕过思路是构造一个不会被简单字符串匹配删除的Payload。大小写混淆ScRiPtalert(1)/sCrIpT。str_replace是大小写敏感的它只找全小写的script。嵌套标签scrscriptiptalert(1)/script。假设过滤逻辑是删除一次“

本月热点