ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

DVWA实战:反射型XSS从入门到防御全解析

DVWA实战:反射型XSS从入门到防御全解析 1. 从DVWA认识反射型XSS先搞清楚你在打什么第一次打开DVWA靶场很多人点进XSS(Reflected)模块后是一脸懵的——页面上就一个输入框和一个Submit按钮输入什么就回显什么看不出任何门道来。这其实是学习XSS最好的起点因为反射型XSSReflected Cross-Site Scripting是最基础、最直观、也最容易理解的一类Web漏洞你在DVWA里做的每一步操作都能在真实业务系统中找到一一对应的场景。DVWADamn Vulnerable Web Application是一个开源的PHPMySQL环境靶场专门用来练习Web安全测试。它不是真实的“漏洞网站”而是一个合法、可控、供安全从业者和爱好者练手的实验平台。这一点很重要——你在这里做的所有攻击测试都是被授权的、安全环境内的行为和去真实网站“打点”完全是两回事。靶场里每个漏洞模块都分了Low、Medium、High、Impossible四个难度级别这四个级别实际上就是真实互联网上Web应用安全防护水平从裸奔到及格线的缩影。反射型XSS的核心特征是“一次性”和“即时反射”。攻击者把恶意脚本写在URL参数里用户点开这个构造好的链接页面把参数值原样输出到HTML里脚本就在用户的浏览器里执行了。注意脚本是在“用户自己的浏览器”里执行的不是在服务器上执行——这一点很多人刚接触时会搞混。XSS攻击的是用户而不是服务器所以它的危害往往是以用户的身份发起请求、窃取用户的数据、盗取用户的Cookie等等。先入个门把XSS家族的关系理清楚。反射型XSSReflected是“你发给我一个链接我点开就中招”存储型XSSStored是“你发一段评论存在了服务器上以后每个看评论的人都中招”DOM型XSSDOM Based则是“页面本身的JavaScript代码在操作DOM时把不可信数据拼进了动态渲染里”。回头你打DVWA的时候会连着三个XSS模块都过一遍它们之间的差别会在实战中越刻越清楚。这篇文章我们就只聚焦在反射型XSS这一个点上把DVWA的Low、Medium、High三个难度全部走一遍不只要告诉你“怎么过关”更重要的是讲清楚“为什么这样写能绕过”“被过滤掉了该怎么想下一种方案”以及“真正开发时该怎么防住这类问题”。毕竟打靶场的目的不是截图打卡而是把攻击手法和防御思想内化成自己的判断力。2. 环境准备15分钟把DVWA跑起来工欲善其事必先利其器。DVWA的搭建方式有很多这里我推荐“PHP内置服务器 手工配置”的方式原因是我觉得用Docker虽然一条命令就能搞定但少了手工配置的过程你对Web服务、数据库连接、配置文件这些底层东西的理解会薄弱不少。学安全的初期我还是建议动手多一点出错多一点记忆才牢靠一点。2.1 三种搭建方式怎么选DVWA的搭建方案我梳理下来主要有下面三条路Docker一键部署代码仓库里有docker-compose配置一条命令拉起环境。优点是快缺点是环境太“黑盒”你连不上数据库时很难判断是哪一层出了问题。PHPStudy/宝塔面板 手动部署适合在Windows上操作的初学者图形化管理MySQL和Apache/Nginx排查问题方便。原生LAMP/LNMP手工部署最折腾但也最练习基本功。我建议有点Linux基础的同学走这条路。我个人在给身边朋友推荐的时候默认是Windows下用PHPStudy因为国内学安全的同学很多主力机就是WindowsPHPStudy装好了Apache和MySQLDVWA丢进去就能跑省去很多不必要的环境折腾。2.2 手工配置DVWA的关键节点如果你选择手工配置需要注意几个关键点。下载DVWA源码后解压放到Web根目录进入config目录把config.inc.php.dist复制一份重命名为config.inc.php然后打开编辑。需要修改的核心配置在数据库连接部分$_DVWA[ db_server ] 127.0.0.1; $_DVWA[ db_database ] dvwa; $_DVWA[ db_user ] dvwa; $_DVWA[ db_password ] pssw0rd;默认的用户名密码不是root/123456而是dvwa/pssw0rd。很多人卡在这一步数据库连不上就一直白屏其实是这里没改。改成你本机实际的MySQL账号密码即可。浏览器访问http://127.0.0.1/dvwa会进入安装页面点一下“Create / Reset Database”按钮出现Database has been created说明数据库初始化成功。然后使用默认账号admin/password登录。初次登录后DVWA会提示你修改密码改一个自己记得住的就行。注意DVWA的PHP版本兼容性是个大坑。如果你用的是PHP 8.1以上版本旧版DVWA很可能出现一些函数弃用警告甚至直接白屏。建议对应DVWA官方仓库的Release版本选择匹配的PHP环境1.9版配PHP 5.6最新版2.x系列对PHP 7.4/8.0都兼容。实测下来PHP 7.4是最稳的省心。登录进去之后先把页面右下角或者菜单里的Security Level安全级别设置为Low。DVWA的XSS模块在最左侧菜单的XSS(Reflected)点进去就是我们要打的目标了。3. Low级别连过滤都没有这是最原始的XSS3.1 界面分析和通关操作Low级别的反射型XSS页面特别简单核心代码逻辑也很直白。你输入一个名字点Submit它把名字放到一个Hello开头的话里回显出来。我第一次打这个级别的时候第一反应是在输入框里敲几个字母测一下回显位置比如输入zhangsan页面显示Hello zhangsan.然后我直接输入了XSS最经典的验证Payloadscriptalert(XSS)/script页面弹出XSS提示框弹窗的那一刻说明脚本在用户的浏览器上下文里执行成功了。过关条件达成。3.2 Low级别的源码解读DVWA的Low级别源码并不复杂核心逻辑就是把$_GET[name]获取到的参数值原封不动地拼接进HTML里输出。也就是说用户的输入从进入系统到被浏览器解析中间没有任何过滤、转义、白名单校验。这里要记住一个关键结论凡是把用户可控数据直接拼接进HTML输出的位置都存在XSS的潜在可能是否有过滤只决定利用难度不决定漏洞是否存在。用浏览器的开发者工具看网络请求会更直观。点击Submit后Network面板里能看到URL变成了http://127.0.0.1/dvwa/vulnerabilities/xss_r/?name%3Cscript%3Ealert%28%27XSS%27%29%3C%2Fscript%3E%3C就是的URL编码形式。这说明数据是通过GET请求的name参数传进去的。在真实攻击场景里攻击者会把这个完整URL发给受害者受害者已经登录了某个系统点开链接就触发脚本。实操心得在实验的时候建议打开浏览器开发者工具的“Preserve log”这样每次提交后看到的还是上一次的完整请求和响应内容。很多时候问题不在Payload本身而是你看不到浏览器究竟把什么发送给了服务器。3.3 Low级别的核心技术点总结Low级别虽然简单但有几个点值得消化GET参数反射回显输入点、输出点都在同一个请求里这是反射型XSS的基本结构。无过滤无转义服务器直接拼接输出这是漏洞存在的根本原因。浏览器解析执行script标签被浏览器当成HTML结构解析脚本随即执行。风险等级低级难度对应真实世界中“完全没做安全防护”的老旧应用教你认识最原始的漏洞形态。4. Medium级别过滤了script但你还有一百种写法进入Medium级别后先试试老套路。输入scriptalert(XSS)/script点击提交页面没有弹窗而是把这段内容原样显示出来了还夹了一串乱码。这时候网上很多教程会让你直接换成img srcx onerroralert(XSS)一试就弹窗了。但如果你只停留在“抄Payload过关”的层面遇到下一个变种就又会卡住。我们得搞清楚Medium到底过滤了什么。4.1 Medium级别的过滤逻辑DVWA的Medium级别源码里对输入做了这样一个处理$name str_replace( script, , $_GET[ name ] );也就是说它对script这个字符串做了替换替换成空字符串。这句话透露的信息特别关键它过滤的只是小写字母的script这一个固定字符串而不是“脚本标签”这个HTML概念。明白了这一点绕过的思路就有了。第一大小写绕过。script被替换了那SCRIPT、ScRiPt呢这些变体都能绕过基于固定字符串匹配的过滤浏览器解析HTML标签时不区分大小写所以SCRIPTalert(xss)/SCRIPT照样能弹窗。第二双写绕过。因为过滤是“把script删掉”那你输入scrscriptipt它把中间的script删掉后就成了script完美接合。这种绕过方式在真实漏洞中也很常见很多WAF规则做简单字符串替换时都踩过这个坑。第三换标签。script被过滤了关键是“能执行JavaScript事件的标签”不止它一个比如img srcx onerror...、svg onload...、body onload...都很经典。它们不需要一个完整的script标签而是通过事件属性触发脚本执行。4.2 Medium级别的完整通关路径实际到我操作的时候Medium级别我试的顺序是这样的。为了验证过滤规则我首先输入一段普通文本确认回显正常。然后输入scriptalert(1)/script排除干扰再输入大写版本SCRIPT弹窗成功这说明过滤不是大小写不敏感的。如果测试环境对大小写也做了处理我就会换用事件标签来打。这里我推荐用img srcx onerroralert(document.cookie)来验证。只要图片加载失败src的值x不存在就会触发onerror事件来执行JavaScript。在DVWA里弹一下Cookie你会立刻意识到如果这是一台真实业务的服务器攻击者可以用这种方式偷走用户的会话凭证。注意Medium级别虽然过滤了script但页面还是会处理其他HTML标签的所以用img这类标签方式完全合法弹窗后即视为通过。测试时建议把浏览器的缓存关掉避免每次都用旧页面影响判断。4.3 Medium级别暴露的常见认知误区我见过很多初学者在Medium级别犯同一个错误试了一两种Payload没生效就急着去网上搜答案搜到img绕过后就完事了。这样做虽然能过关但学习效率很低。真正应该做的是在过关之后回头推演一遍服务器究竟过滤了什么为什么这个Payload能生效如果过滤规则改成“过滤所有尖括号”我还能用什么办法这一个自我提问的训练比刷十个靶场都值钱。我在带人的时候常说一句话不要背Payload要背绕过思路。Payload是死的WAF规则是活的只有思路能跟着场景变。5. High级别正则过滤下怎么找活路High级别的页面和Low、Medium从外表上看没什么区别但同一句话回显出来输入scriptalert(XSS)/script已经不再弹窗。查看源码你会发现DVWA在High级别使用了正则表达式来过滤$name preg_replace( /(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i, , $_GET[ name ] );这串正则是什么意思呢它匹配的是“以开头中间任意内容然后按顺序出现s、c、r、i、p、t这几个字母”并且是大小写不敏感的末尾的i修饰符。这意味着你可以在s c r i p t这些字母之间插入任意字符只要连起来能构成script照样会被删掉。所以scrscriptipt双写在这里还有用吗我们推演一下正则匹配到script之后替换成空字符串但因为没有循环处理它删掉一个匹配后就把结果输出了。双写scrscriptipt被处理后变成script还是能逃过一劫——不过这只是针对这一条特定规则而言。5.1 High级别的过滤短板在哪里这条正则看着挺唬人其实短板也很明显。它只处理了script这一个标签完全没有考虑其他标签和JavaScript事件。所以img src1 onerroralert(xss)这类Payload在这个规则下畅通无阻因为里面压根就不含script这个词。另一个漏洞是它的.*配的是“非换行任意字符”而且在Perl兼容正则里.*默认是贪婪匹配并且可以匹配尖括号本身。你构造特殊Payload时可以利用这个特性做更多变形。不过作为练习High级别的目标就是让你意识到只过滤danger标签的黑名单思路是有穷的总有你想不到的标签可以触发脚本。客观说一句DVWA的High级别在实际对抗强度上不算高它更像是在提醒你黑名单过滤不靠谱。真正安全的做法是白名单校验——只用允许的字符其余一律拒绝。这才是High级别更值得深思的地方。5.2 High级别的实操验证过程我实际在High级别下做了一组测试记录一下测试结果输入Payload页面输出是否会弹窗scriptalert(1)/script内容被清除否SCRIPTalert(1)/SCRIPT内容被清除否scrscriptiptalert(1)/scr/scriptipt输出为scriptalert(1)/script是img srcx onerroralert(1)原样输出是svg onloadalert(1)原样输出是svg onloadalert(1)原样输出是取决于上下文从表格可以明显看出凡是和script沾边的一律被删凡是不沾边的就放行。所以这关的高效解法其实就一个换标签。不需要在正则上死磕。5.3 High级别的过关实操建议实际操作的时候点击Submit后页面会把结果回显在一个pre标签内输入内容直接嵌入到Hello的文本节点里。为了保证Payload能被浏览器解析执行这个输入点其实对Payload有一些额外要求——但这不影响我们用img srcx onerroralert(XSS)直接打到弹窗。我建议在High级别顺手做一个测试在Chrome里右键查看页面源代码搜索一下你的Payload字符串看它是出现在HTML的文本节点里还是属性里。这个观察习惯对后续学DOM XSS、存储型XSS都很有帮助能帮你快速判断Payload的构造方式是不是对的。6. 深入理解反射型XSS的原理与危害6.1 XSS的触发链路反射型XSS完整跑通一次链路是这样的受害者已经登录了目标网站浏览器持有了有效的会话Cookie。攻击者构造一个恶意URL把JavaScript代码放在参数里通过邮件、聊天工具发给受害者。受害者点击链接浏览器向目标服务器发起GET请求服务端把参数里的恶意代码拼接进HTML页面并返回。浏览器解析响应执行了恶意脚本。恶意脚本在受害者的浏览器权限下运行能窃取Cookie、模拟用户操作、篡改页面内容。这个链路里最关键的一环是第3步的“拼接输出”。服务端如果对用户输入做HTML实体编码把变成lt;、变成gt;那么用户输入就只是普通文本浏览器不会把它解析成标签。DVWA Low级别的漏洞根源就是它没做这一步编码。6.2 反射型XSS能做什么反射型XSS虽然是一次性的、需要诱导用户点击但它的实际危害取决于业务系统的重要程度。如果目标是一个后台管理系统攻击者可以利用反射型XSS配合其他手段盗取管理员会话实现“登录态劫持”如果目标是一个电商网站攻击者可以模拟用户发起下单、改密码等请求如果目标是一个企业邮箱系统攻击者可以读取页面内的敏感数据甚至截取邮件内容。从攻击者视角来看反射型XSS通常是组合拳中的一环很少单兵作战。比如先找一个反射型XSS再配合短网址服务做个伪装链接诱导用户点击然后截获后面跳转到的业务数据。理解这一点你就知道为什么有些企业会花大力气做XSS防护了——单看一个弹窗没什么大不了但当你把它放在真实的业务链路上看那就是另一回事了。6.3 XSS、CSRF和Cookie劫持的关系打靶场的时候很多人会遇到一个困惑XSS和CSRF跨站请求伪造到底啥区别其实两者相辅相成。XSS是利用用户对网站的信任来执行脚本CSRF是利用网站对用户的信任来伪造请求。如果网站有XSS漏洞攻击者完全可以借XSS构造一个CSRF的请求实现“用用户的身份做坏事”。所以很多CSRF攻防文章里第一步往往都是“先找一处XSS”这两者经常成对出现。DVWA里专门有CSRF模块你可以等打完XSS之后再去对比着练。到时候你就会发现反射型XSSCSRF的组合在很多系统里就能形成一条完整的攻击链。7. 反射型XSS的防护从攻击视角切换到防御视角打靶场如果只打攻击不学防御等于只练了矛没练盾。我们切换到开发者视角看看DVWA的源码里给出的“标准答案”是什么样的。7.1 Impossible级别的标准防御方案DVWA的Impossible级别是“通关标准答案”它给的防御措施很典型$name htmlspecialchars( $_GET[ name ] );核心就这一行。htmlspecialchars函数会把HTML中的特殊字符转成实体变成lt;变成gt;变成amp;变成quot;。经过这个函数处理后的内容浏览器都会当成普通文本展示不会去解析成标签。这就从根上断掉了XSS的可能。此外Impossible级别还加了一个token验证防止跨站请求直接构造URL调用这个页面。这是CSRF层面的防御和XSS防御是两层独立的事。打DVWA到Impossible级别时可以注意看一下页面代码里多了哪些函数每个函数起什么作用。7.2 真实开发中的三重防护思路在真实业务开发中XSS防护不会只有一行代码而是分层配合的输入侧对用户的输入做合法性校验白名单只允许预期格式的数据比如姓名只允许中文和字母邮箱必须符合邮箱格式数字必须是整数。输出侧在把用户数据输出到HTML前用htmlspecialchars或框架自带的模板转义机制做编码处理。请求侧部署CSP内容安全策略响应头限制页面可以加载和执行的脚本来源就算有XSSCSP也能很大程度上限制恶意脚本的执行。有一点必须强调防御的核心是输出编码不是输入过滤。Web安全领域有个经典案例某个系统尝试用“过滤掉所有script”来防XSS结果被img onerror轻松绕过——这正是你在DVWA Medium和High级别里亲身验证过的事情。所以如果你将来参与开发或代码审计看到系统只用黑名单过滤HTML标签要立刻意识到这条路走不通。7.3 开发者常见的XSS防护误区配合DVWA的练习我想特别列出我在平时开发中常见的误区供大家对照自查只在Java端做转义前端模板里直接拼接HTML字符串——等于没防。对输入做了trim、addslashes但忘了在输出位置做转义——等于没防。用了富文本编辑器却只过滤了script没有过滤iframe、svg、事件属性——等于没防。以为post请求就安全了忘记get请求和post请求都能携带恶意参数——等于没防。这些问题在DVWA的练习里都能找到对应影子。如果你在打靶场时有过“我明明过滤了怎么还是弹窗”的困惑那恭喜你你已经离真正的防护认知很近了。8. 常见问题与排查技巧实录打DVWA反射型XSS的时候新手遇到的大部分问题其实不在漏洞本身而是一些环境或操作细节。我整理了一份问题速查表现象可能原因解决办法页面一直白屏PHP版本过高代码兼容性问题降到PHP 7.4或升级到最新DVWA版本数据库报连接失败config.inc.php里数据库账号密码不对修改为实际MySQL账号密码确认数据库已创建弹窗一闪而过浏览器XSS筛选器拦截了换个本地浏览器或关掉相应安全选项DVWA本地环境可直接忽略Payload没弹窗安全级别没切到对应难度检查DVWA菜单右下角的Security Level设置号变成空格URL编码问题GET参数里的被解析为空格用%2B代替或使用%20做空格看不清参数位置不知道输入点在哪按F12打开开发者工具切到Network看请求URL反射内容在pre标签里页面回显位置在文本节点先测引用和括号再构造带标签的Payload最典型的一个操作问题是很多人不看URL直接在页面输入框里敲Payload。DVWA的反射型XSS的输入会和URL绑定点击Submit其实是在构造一个GET请求。如果你使用的是XSS测试浏览器地址栏会原样展示Payload编码后的URL。看懂这个URL你就能理解反射型XSS“一次请求一次响应”的本质。还有一个容易被忽略的小坑Chrome和Firefox内置了XSS Auditor现在Chrome已经移除了这个机制老版本Firefox仍然有有时候你明明输入了正确的Payload页面却弹不出窗那就是浏览器在客户端层面拦截了反射型XSS。本地靶场可以让浏览器放行或者直接换一个没有该拦截机制的测试浏览器。9. 实操总结与后续练习建议DVWA反射型XSS这一路打下来从Low到High到Impossible你其实经历了完整的“发现漏洞—利用漏洞—分析过滤—绕过过滤—理解防御”过程。这套思路框架不只在XSS上适用在SQL注入、文件包含、命令注入等所有DVWA漏洞模块里都能复用。接下来我建议你按照这个顺序继续练把DVWA的XSS三个级别全部重打一遍但这次不打开源码纯黑盒测试看能不能自己推算出过滤规则。对照源码阅读把每个级别的过滤函数、输出位置、防护措施一条条记录下来。去DVWA的存储型XSS和DOM型XSS模块对比三种XSS之间的差异。找一个合法的漏洞测试平台比如本地搭建的其他靶场练手把反射型XSS的Payload在不同上下文HTML标签内、属性内、JavaScript代码中的写法都试一遍。自己用原生PHP写一个简单的留言板故意不做输出编码亲手复现一次XSS然后再修复它。这个过程是理解XSS最有效的方法。我个人带人入门时有一个不太一样的习惯会故意让新手在DVWA里先“把页面玩坏”——输入各种奇怪的字符看看输出有什么变化然后在源码里找到对应的处理逻辑。这种“破坏式学习法”看起来进度慢但建立的认知基础远比照着教程一步步过关要扎实得多。打靶场不是任务而是你建立攻击者思维最好的训练场。关于反射型XSS最后再多说一句这个漏洞在今天的真实互联网上依然大量存在只是随着前端框架的普及触发位置从服务端模板转移到了前端JavaScript渲染层。你从DVWA里学到的思路放到现在依然有效唯一需要更新的是Payload的写法。这就是这门手艺有意思的地方——攻击手法永远在变但是追本溯源的思路始终是通用的。
返回列表