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

去年我演示过一个简单的方法在 Edge 上进行 referrer 欺骗,可以用来欺骗 referer,还有额外惊喜:比如 XSS 过滤器的绕过。

今天我发现它已经被修复了,于是我决定找到绕过补丁的方法。老实说,我认为这不是一种绕过而是一些改动。实际看来,它依然有效地绕过了补丁,但从技术的角度来说,绕过方法有所不同。无论哪种方法,搞起!

修复前的原始 PoC

在原博文中我们可以看到,仅通过打开一个带着对应 referrer 的新窗口,然后跳转至目标域即可实现 referrer 欺骗。两行代码值千言。查看下面的 PoC,whatismyreferrer.com 认为referrer 是 paypal.com,实际上应该是执行 location.href 的页面的 URL(现在已经被修复)。

win = window.open("https://www.paypal.com");  
win.location.href = "https://www.whatismyreferer.com";  

这足以欺骗 Edge 上的 referrer ,但是现在它已修复,而我突然想起一个简单的变通方法。这里没有调试或分析,显然只是大胆测试,迅速且奏效。

我试了几种方法来更改最终 URL(除了 location.href,采用 location.replace,meta 刷新,window.open 等方法),看看 Edge 能否被欺骗,却未能如愿。但是,如果从 iframe 内部更改 URL,会发生什么?referrer 会变成页面顶部还是 iframe 的 URL?

Playing with the referrer

在回答问题之前,请记住一个概念,通常 referrer 的网址应该是发起请求的网址。假设我们的 facebook.com 有一个 iframe 指向 eval.com,如果iframe 将顶部的 URL 更改为 paypal.com,那么 paypal 接收到的 referrer 应该是 evil 而不是 Facebook。

上图显示了预料到的结果(正确的),即使是在 Edge 上也是如此。但是如果不使用常规的链接跳转,而是通过使用 location.href 设置顶部的 location ,然后 Edge 会搞混,使用其顶部的地址作为 referrer。

以下便是一个简单的测试页面,其中显示了常规链接跳转和 location.href 之间的区别。二者都会把你带到 whatismyreferer.com,但是你会看到常规链接正确跳转了,而 top.location.href 没有。

[ 漏洞演示页面 ]

但是我们如何利用这个漏洞呢?显然,Facebook 永远不会提供恶意的 iframe 对吧?好吧,Facebook 其实会像雅虎这样的大厂商提供 iframe 广告服务。这些广告会代表这些大型网站加载任何网页。此外,使用 top.location.href 的话,这些广告可以毫无障碍地绕过 XSS 过滤器。

就个人而言,我讨厌理论上的漏洞,因为这根本无法让我满意。你懂的,“如果用户点击此处,接受警告,解压文件,双击exe,他就被感染了”。我并不喜欢这样。

为了达到有效利用的目标,通过将 iframe 注入到要欺骗referrer 的站点中,然后从中执行 top.location。这与在任何网站上放置 iframe 上是一个道理,但是我们不需要任何相关合作!此话怎讲?我们希望 whatismyreferer.com(受害者)相信用户是来自 paypal.com(假的 referrer)。 而计将安出?

注入 iframe

  1. 打开新窗口,将服务器重定向至 PayPal
  2. 重定向发生之前,注入 iframe
  3. 重定向发生时,在 iframe 中用 top.location 跳转至 whatismyreferer.com

关于这个 iframe 注入,之前关于 IE 的文章 htmlFile/UXSS 有所提及,这里我们再回顾一下吧。

当我们通过服务器重定向(1)打开新窗口时,我们有一点儿时间(重定向发生之前)访问它的DOM,这便是注入iframe(2)的时机。一旦重定向发生,Edge将尽力删除页面(包括我们的iframe)中的所有内容并渲染PayPal,但是我们将通过阻塞线程阻止这一步。然后,一旦重定向发生,解锁该线程,并从iframe内部执行一个top.location.href(3)。

这种特殊情况下,我们使用了与这两处(xss-ie-domainless-worlduxss-ie-htmlfile)相同的技术阻塞线程,可以看到一个简陋的大大的 alert。当然有办法在不需要用户交互和 alert 的情况下阻塞线程,但我不想让攻击者太轻松地实现。如果 PoC 会弹出 alert,且必须进行用户交互,这就显得用处不大了。这里有完整的 PoC:

// Open a new window with a server redirect to paypal
var win = window.open("redir.php?URL=https://www.paypal.com");

// Create an iframe immediately, before it redirects
var ifr = win.document.createElement("iframe");  
win.document.appendChild(ifr);

// Make sure the iframe has access to its top (otherwise it will lose it)
win[0].opener = win;

// Block the iframe and once the redirect happens, move to the victim website.
win[0].setTimeout("alert('Close me once the site starts loading behind');" +  
                   "opener.location='https://www.whatismyreferer.com'");

[ Test the PoC Live on Edge ]

捉虫猎手学无止境。关掉Facebook标签,读一些有趣的东西吧。生如夏花,死如秋叶,莫要徒劳无功。继续学习,有所取舍,然后享受你的成果!

Have a nice day! 🙂