一同源策略
同源策略是浏览器最重要的一种安全机制,由Netscape于1995年最先提出,现在的主流浏览器都遵循这种策略[1]。同源一般指协议,域名,端口都相同,但IE浏览器会忽略对端口的判断。RFC 6454定义了计算同源URL的算法[2]。为了形象的描述同源URL,下表给出了特定URL是否与http://www.360.cn/weishi/index.html同源的计算结果和原因。
被比较的URL
|
比较结果
|
原因
|
http://www.360.cn/index.html
|
同源
|
协议和域名都相同
|
http://www.360.cn/weishi/updatelog.html
|
同源
|
协议和域名都相同
|
http://360.cn/index.html
|
非同源
|
域名不同
|
http://shouji.360.cn/index.html
|
非同源
|
域名不同
|
http://www.360.cn:8088/index.html
|
非同源
|
端口不同
|
https://www.360.cn
|
非同源
|
协议不同
|
http://www.google.com
|
非同源
|
域名不同
|
file:///C:/Program%20Files/360/
|
非同源
|
协议与域名都不相同
|
同源策略限制javascript只能操作同源站点的DOM对象。用如下所示的HTML脚本来简单说明同源策略对javascript的限制,首先用IFrame将www.so.com 嵌入到某html中,假设为sop.html,并在sop.html的javascript中操作www.so.com的dom对象。
<html> <iframesrc="http://www.so.com" id="360"></iframe> <script> console.log(document.getElementById("360").contentDocument.body); </script> </html>
将此html上传到你的站点,假设为www.yousite.com,然后访问此页面,你会得到如下所示的安全错误异常,以下所示为chrome的控制台输出,表示上述访问违反了同源策略。
Uncaught SecurityError: Blocked a frame with origin “http://www.so.com” from accessing a frame with origin “http://www.yoursite.com”. Protocols, domains, and ports must match.
对file协议的同源性判断,不同浏览器在不同的时期判断标准都不同,当javascript脚本通过非file url(如http url)加载执行时,file url都被判断为非同源url,这样可以阻止http页面中的javascript读取本地文件。当javascript通过file url加载执行时,有的浏览器允许JS访问所有的本地文件,有的以目录作为同源性判断条件,有的仅仅允许访问url特指的文件。在file url的javascript中访问其它协议的资源,也是不同时期不同的浏览器有不同标准,有的允许在file协议中通过XmlHttpRequest请求http资源,有的则不允许。
我们通过一个简单示例和4个API来理解WebView中file协议的安全性,示例代码如下,4个API见4行注释,分别用(1)–(4)表示。
public class WebViewActivity extends Activity { private WebView webView; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_webview); webView = (WebView) findViewById(R.id.webView1); //webView.getSettings().setAllowFileAccess(false); (1) //webView.getSettings().setJavaScriptEnabled(true); (2) //webView.getSettings().setAllowFileAccessFromFileURLs(true); (3) //webView.getSettings().setAllowUniversalAccessFromFileURLs(true); (4) Intent i = getIntent(); String url = i.getData().toString(); webView.loadUrl(url); } }
其中WebViewActivity为导出Activity,当其它应用启动此Activity时intent中的data直接被当做url来加载。通过drozer可以很方便的启动WebViewActivity,运行如下所示的命令,WebViewActivity会加载file:///data/local/tmp/attack.html
dz> run app.activity.start
–component com.example.webviewtest com.example.webviewtest.WebViewActivity
–action android.intent.action.VIEW
–data-uri file:///data/local/tmp/attack.html
–component com.example.webviewtest com.example.webviewtest.WebViewActivity
–action android.intent.action.VIEW
–data-uri file:///data/local/tmp/attack.html
我们知道因为sandbox的存在, Android中的各应用是相互隔离的,在一般情况下A应用是不能访问B应用的文件的,但不正确的使用WebView可能会打破这种隔离,从而带来应用数据泄露的威胁,即A应用可以通过B应用导出的Activity让B应用加载一个恶意的file协议的url,从而可以获取B应用的内部私有文件。我们分别分析4个API对WebView安全性的影响。
通过这个API可以设置是否允许WebView使用File协议,默认值是允许,如果不允许使用File协议,则不会存在下述的各种跨源的安全威胁,但同时也限制了webview的功能,使其不能加载本地的html文件。禁用File协议后,运行上述drozer命令会得到下图所示输出,图中所示的文件是存在的,但WebView禁止加载此文件,移动版的Chrome默认禁止加载file协议的文件。
2 setJavaScriptEnabled
通过此API可以设置是否允许WebView使用JavaScript,默认是不允许,但很多应用,包括移动浏览器为了让WebView执行http协议中的javascript,都会主动设置允许WebView执行Javascript,而又不会对不同的协议区别对待,比较安全的实现是如果加载的url是http或https协议,则启用javascript,如果是其它危险协议,如是file协议,则禁用javascript。禁用file协议的javascript可以很大程度上减小跨源漏洞对WebView的威胁。当然,禁用file协议的javascript执行并不能完全杜绝跨源文件泄露。例如,有的应用实现了下载功能,对于不可渲染的页面,会自动下载到sd卡中,由于sd卡中的文件所有应用都可以访问,于是可以通过构造一个file URL指向被攻击应用的私有文件,然后用此URL启动Activity,就可以在SD卡中读取被攻击应用的私有文件了。
3 setAllowFileAccessFromFileURLs
通过此API可以设置是否允许通过file url加载的Javascript读取其他的本地文件,这个设置在JELLY_BEAN以前的版本默认是允许,在JELLY_BEAN及以后的版本中默认是禁止的。下面的代码片段为对应于与drozer命令中的attack.html。
<script> function loadXMLDoc() { var arm = "file:///etc/hosts"; var xmlhttp; if (window.XMLHttpRequest) { xmlhttp=new XMLHttpRequest(); } xmlhttp.onreadystatechange=function() { //alert("status is"+xmlhttp.status); if (xmlhttp.readyState==4) { console.log(xmlhttp.responseText); } } xmlhttp.open("GET",arm); xmlhttp.send(null); } loadXMLDoc(); </script>
当AllowFileAccessFromFileURLs为true是,上述javascript可以成功读取/etc/hosts的内容,但设置为false时,上述脚本执行会导致如下错误,表示浏览器禁止从file url中的javascript读取其它本地文件。
I/chromium(27749): [INFO:CONSOLE(0)] “XMLHttpRequest cannot load file:///etc/hosts. Cross origin requests are only supported for HTTP.”, source: file:///data/local/tmp/attack.html
4 setAllowUniversalAccessFromFileURLs
通过此API可以设置是否允许通过file url加载的Javascript可以访问其他的源,包括其他的文件和http,https等其他的源。这个设置在JELLY_BEAN以前的版本默认是允许,在JELLY_BEAN及以后的版本中默认是禁止的。如果此设置是允许,则setAllowFileAccessFromFileURLs不起做用,假设下面的代码片段为对应于与drozer命令中的attack.html。
<script> function loadXMLDoc() { var arm = "http://www.so.com"; var xmlhttp; if (window.XMLHttpRequest) { xmlhttp=new XMLHttpRequest(); } xmlhttp.onreadystatechange=function() { //alert("status is"+xmlhttp.status); if (xmlhttp.readyState==4) { console.log(xmlhttp.responseText); } } xmlhttp.open("GET",arm); xmlhttp.send(null); } loadXMLDoc(); </script>
当AllowFileAccessFromFileURLs为true是,上述javascript可以成功读取http://www.so.com的内容,但设置为false时,上述脚本执行会导致如下错误,表示浏览器禁止从file url中的javascript访问其他源的资源。
I/chromium(28336): [INFO:CONSOLE(0)] “XMLHttpRequest cannot
load http://www.so.com/. Origin null is not allowed by
Access-Control-Allow-Origin.”, source: file:///data/local/tmp/attack.html
load http://www.so.com/. Origin null is not allowed by
Access-Control-Allow-Origin.”, source: file:///data/local/tmp/attack.html
三 使用符号链接跨源
为了安全的使用WebView, AllowUniversalAccessFromFileURLs和AllowFileAccessFromFileURLs都应该设置为禁止,在JELLY_BEAN及以后的版本中这两项设置默认也是禁止的,但是即使把这两项都设置为False。通过File URL中的javascript仍然有方法访问其他的本地文件。通过符号链接攻击可以达到这一目的,前提是允许file
URL执行javascript。这一攻击能奏效的原因是无论怎么限制file协议的同源检查,其javascript都应该能访问当前的文件,通过javascript的延时执行和将当前文件替换成指向其它文件的软链接就可以读取到被符号链接所指的文件。具体攻击步骤见Chromium
bug 144866[3]. 因为Chrome最新版本默认禁用file协议,所以这一漏洞在最新版的chrome中并不存在,Google也并没有修复它,但是大量使用WebView的应用和浏览器,都有可能受到此漏洞的影响。比如某手机浏览器就存在此漏洞,通过利用此漏洞,无特殊权限的恶意APP可以盗取浏览器的任意私有文件,包括但不限于Cookie, 保存的密码,收藏夹,历史记录,并可以将所盗取的文件上传到攻击者的服务器。下图为通过file URL读取某手机浏览器Cookie的截图
URL执行javascript。这一攻击能奏效的原因是无论怎么限制file协议的同源检查,其javascript都应该能访问当前的文件,通过javascript的延时执行和将当前文件替换成指向其它文件的软链接就可以读取到被符号链接所指的文件。具体攻击步骤见Chromium
bug 144866[3]. 因为Chrome最新版本默认禁用file协议,所以这一漏洞在最新版的chrome中并不存在,Google也并没有修复它,但是大量使用WebView的应用和浏览器,都有可能受到此漏洞的影响。比如某手机浏览器就存在此漏洞,通过利用此漏洞,无特殊权限的恶意APP可以盗取浏览器的任意私有文件,包括但不限于Cookie, 保存的密码,收藏夹,历史记录,并可以将所盗取的文件上传到攻击者的服务器。下图为通过file URL读取某手机浏览器Cookie的截图
截图只是简单的将得到的Cookie文件alert出来,实际攻击可上传文件至攻击者服务器。我们对20个有导出WebView的应用进行分析发现,30%的应用不能抵抗这种攻击。
四 安全建议
1.对于不需要使用file协议的应用,禁用file协议
2.对于需要使用file协议的应用,禁止file协议调用javascript
引用
[1] http://en.wikipedia.org/wiki/Same-origin_policy
[2] http://tools.ietf.org/html/rfc6454
via:http://blogs.360.cn/360mobile/2014/09/22/webview%E8%B7%A8%E6%BA%90%E6%94%BB%E5%87%BB%E5%88%86%E6%9E%90/
没有评论:
发表评论