一同源策略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