0%

xs-leak(Cross Site Leak)攻击

XS-Leak攻击本质上是一个浏览器侧信道攻击,可被用来推断并收集用户信息。很早这种利用方式就出现了。11年前,即2009年,Chris Evans利用恶意网站,构造不同的关键词搜索访问者电子邮件收件箱的内容。根据返回的时间判断该关键字是否存在,时间长则说明存在该关键词,反之依然。它存在的问题是影响时间的因素很多,准确度难以保证。在6年后,Nethanel Gelernter和Amir Herzberg将其命名为XSSearch,利用统计学的方法使结果更加可靠。而现在又出现的是利用缓存技术来判断查询的结果,它被叫做HTTP缓存跨站点泄漏

0x01 基于时间的判断方式

基于时间的xs-leak在测量时间差时,在请求资源的前后分别记录下时间。然后时间差作为判断的依据。

1
2
3
let before = performance.now()
await fetch("//mail.com/search?q=foo")
let request_time = performance.now() - before

0x02 XSSearch方式

1.Chrome Xss Auditor

这里利用了一个特性,即在chrome中通过iframe打开一个页面,当被正确加载时修改window.hash不会出发iframe的onload事件;但是当页面加载错误时,修改iframe的hash会再一次触发onload事件。

得出了以下逻辑:
页面加载成功: 与页面内容不匹配
页面加载失败: 与页面内容匹配

匹配出页面中含有的内容

chrome中的XSS auditor本身的逻辑比较简单,判断是否输入敏感payload,输入内容是否在页面中含有。

2.CSS

CSS的这种利用方式也可以用在绕过CSP上。主要用到的是CSS选择器,通过CSS选择器可以对指定的属性加载不同的样式。通过这种方式就能够爆破出属性值。一般可以用来获取CSRF Token、CSP nonce值等。

当input标签的value值以1开头时,向http://vps/1发送请求,以2开头,向http://vps/2发送请求。根据VPS收到的请求就能获取value值。

案例: SECCON2018中有道题目就是利用这样的方式获取csrf token。

3.window.frames.length

window.frames.length表示一个页面包含的frames的数量。

案例: Facebook CTF 2019: Secret_note_keeper.
这道题目中的web应用的目的是存储、查看、搜索notes。用户可以登录、创建、查看、搜索自己的notes,并提交bug报告。一个notes包含一个title和body,用户通过提供字符串来在body中搜索notes。如果所搜匹配到,则会将结果展示在iFrame中。
提交bug报告是提交一个link,然后后台的bot会自动点击。这就可以利用后台的身份,让后台去搜索自己的notes,利用xs-leak获取flag信息。

构造一个特殊页面(页面内容如下),放在自己的VPS上,然后将地址提交给后台。

这段payload也很好理解,通过爆破的方式一位一位地开始搜索以fb{开头的字符串,当匹配成功时结果会放在iframe中,通过判断frames的数量即可判断是否匹配成功,还要记得将结果发送回去。

4.history.length

它的原理和window.frames.length一样,通过判断资源加载前后的history.length有没有增加来判断是否成功加载资源。整个的代码可以写成这样。

1
2
3
4
5
6
7
8
9
10
11
let a = history.length;
ifr = document.createElement('iframe');
ifr.src = "http://xxxx/";
document.body.appendChild(ifr);
let b = history.length - a;

if (b){
console.log("Resource had been loaded");
}else{
console.log("Resouce is not loaded");
}

0x03 HTTP缓存跨站点泄漏方式

HTTP缓存跨站点泄漏攻击实施起来分为3个步骤:

  • 删除目标浏览器中特定的缓存
  • 打开目标浏览器查询相关内容
  • 检查浏览器是否缓存了相关内容

在上面的整个过程中,攻击者需要满足以下能力:

  • 能够删除用户浏览器中的特定缓存。
  • 能够使得用户发起对特定资源的请求。
  • 检查浏览器是否缓存了特定资源

删除缓存
删除缓存的方式有这几种方式:

  • 发送post请求
    • 发送post请求清空缓存的原理是,当该静态资源以post请求当时被请求时,缓存会认为它不是个静态资源,不应该被缓存,因而清空。
  • 使用fetch “reload”以在服务器上返回错误的方式
    • 发送fetch请求时将cache设置为reload,当发生错误时(例如设计超长的HTTP referer)会使得reload的cache为空,从而清空。
  • 设计过长的url,使得服务器报错清空之前的缓存。
    • 当请求静态资源时在后面添加上无用参数,使得达到长度限制,使得服务器报错,浏览器接收到服务器报错后,会清空该静态资源。

发起请求
要让受害者以特定的方式发送请求,在xs-leak的场景中是使得受害者访问攻击者精心设计的网站,这会使得受害者访问特定资源,发送特定的请求。

检查浏览器是否缓存资源
不同的场景有不同的利用方式,在后面会结合案例来说明这种方式。

1.cache with referrer

使用referrer的缓存判断,整个demo代码可从github上获取。这种判断不是根据时间响应来判断,来看看它的工作原理吧。

第一段是利用fetch请求的方式,设置过长的referrer来清空缓存。第二段的内容是打开iframe页面,加载img.jpg资源。然后第三段同样设置了过长的referrer,保证了img.jpg的加载只能从缓存中加载。在加载img.jpg时首先会从缓存中寻找,若没有则请求服务器,但此时由于请求的referrer过长报错,导致服务器不会回应正常的资源。

同时注释中提到了使用cache:force-cache来提高准确率,这是防止缓存过期影响判断。该字段表示fetch请求不顾一切的依赖缓存, 即使缓存过期了, 它依然从缓存中读取. 除非没有任何缓存, 那么它将发送一个正常的request。

0x04其他

在xsleaks的github上还有其他的一些利用,由于并未想出来它有什么影响,暂且归为其他。

  • 检测content-type类型(仅在火狐中有效,因为typeMustMatch仅在火狐中支持)。

根据MDN的解释,HTMLObjectElement.typeMustMatch表示只有链接的资源必须与type相匹配该资源才会被使用。很显然,在这整个过程中,资源会被加载一次。通过这个来判断被请求的资源的content-type。(虽然不知道获取该信息有啥用)

  • 检测资源是否可以被iframe嵌入。(仅在Chrome有效)

通过判断资源是否被嵌入来得出该资源能否被嵌入的结果。

  • 通过是否有下载提示窗口来判断哪些url端点是可以下载文件。
  • 检测跨域服务端重定向

危害

  • 社交网络中获取受害者社交网络的用户名,以确定受害者在社交网络中的身份。
  • 获取用户的toke、身份证号码之类的敏感信息。

防御

  • 禁用HTTP缓存(不太可能)
  • 在所有内容上加上CSRF tokens
  • 使用Same Site=strict cookie对用户进行身份验证。
  • 正确配置X-Frame-Options头部,仅允许信任的站点打开站点的iframe。
  • xs-leak攻击需要频繁地打开页面,请求资源,在一定频率时弹出验证码。

参考