一同源策略javascript
同源策略是浏览器最重要的一种安全机制,由Netscape于1995年最早提出,如今的主流浏览器都遵循这种策略[1]。同源通常指协议,域名,端口都相同,但IE浏览器会忽略对端口的判断。RFC 6454定义了计算同源URL的算法[2]。为了形象的描述同源URL,下表给出了特定URL是否与http://www.360.cn/weishi/index.html同源的计算结果和缘由。html
被比较的URLjava |
比较结果android |
缘由web |
http://www.360.cn/index.html算法 |
同源chrome |
协议和域名都相同浏览器 |
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资源,有的则不容许。
二 WebView中的file协议
咱们经过一个简单示例和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
咱们知道由于sandbox的存在, Android中的各应用是相互隔离的,在通常状况下A应用是不能访问B应用的文件的,但不正确的使用WebView可能会打破这种隔离,从而带来应用数据泄露的威胁,即A应用能够经过B应用导出的Activity让B应用加载一个恶意的file协议的url,从而能够获取B应用的内部私有文件。咱们分别分析4个API对WebView安全性的影响。
1 setAllowFileAccess
经过这个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
三 使用符号连接跨源
为了安全的使用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的截图
截图只是简单的将获得的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
[3]https://code.google.com/p/chromium/issues/detail?id=144866