research on service worker

最近看到SonarSource的一篇博客,roundcube webmail里面的xss漏洞。文中讲到可以利用service worker的技巧来持久化xss。于是来研究一下。

service worker

在mdn上我们可以看到,Service workers essentially act as proxy servers that sit between web applications, the browser, and the network (when available). service worker可以加强离线体验,可以拦截请求,同时使用cache,来达到离线使用web应用的效果。

流程不多叙述,我们主要关注register,以及能够拦截哪些fetch。
register(scriptURL, options),包含scriptURL,options中包含scope。 通过实验,我们发现,scope是跟scriptURL的路径有关。而与包含register这段代码的脚本路径关系不大。

scriptURL最终会转换为绝对地址,我们以相对地址举例。

  • 在子目录中
    scriptURL为/aa/sw.js,那么max scope就是/aa/。当然 你的scope可以定义的更小。在这个scope下面,/aa/及其子目录如/aa/bb/,这里面 发起的请求是可以被拦截到的,比如/aa/bb/cc.html里面请求/top.js或者其他站点的js,这些请求都是可以获取到的。
    当你访问/index.html时,是不会被拦截到的。
    那么,在这种情况下,是否有可能扩大scope呢?也是有的,需要/aa/sw.js的返回Response Header里面包含Service-Worker-Allowed头,如Service-Worker-Allowed : /,这样就可以扩大范围。这种情况利用,还需要能够控制返回header,感觉 不太好利用。
  • 在根目录
    scriptURL为/sw.js,那么max scope就是/,那么你是可以拦截到任何请求了。

其他实验

  • 是否能够替换javascript 在拦截范围内是可以替换的。但是不影响非拦截范围的请求。
    我们仍然以在子目录为例,/aa/sw.js
    比如访问/index.html,会请求/a.js文件。
    而/aa/test.html,里面也会请求/a.js文件,那么我在worker里面,修改/a.js的返回,是否能影响首页访问/index.html加载/a.js呢?
    并不能。 但是/aa/test.html访问/a.js时,是会被替换的。以及/aa/bb/cc.html访问/a.js时,也会被替换。这是因为 首页访问不在scope里面,所以service worker没有拦截,而另外两个在/aa/下面,是可以被拦截到的。

  • 关于持久性 关闭tab之后,再重新打开,仍然是替换之后的结果,说明。确实拥有持久性。因为请求被service worker拦截,worker直接返回cache的结果。

结论

service worker确实可以持久化xss。不过和service worker.js这个文件的路径有关。如果能够控制worker的代码在根目录下,那影响就非常大。 感觉实际利用还是比较受限制的。

另外还有一点,就是sw.js的mime type还得是javascript的mime.

https://www.sonarsource.com/blog/government-emails-at-risk-critical-cross-site-scripting-vulnerability-in-roundcube-webmail/ https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register https://github.com/mdn/dom-examples/tree/main/service-worker/simple-service-worker