防嵌套網頁
比如,最出名的clickhacking就是使用iframe來 攔截click事件。因為iframe享有着click的最優先權,當有人在偽造的主頁中進行點擊的話,如果點在iframe上,則會默認是在操作iframe的頁面。 所以,釣魚網站就是使用這個技術,通過誘導用戶進行點擊,比如,設計一個"妹妹寂寞了"等之類的網頁,誘導用戶點擊,但實際結果,你看到的不是"妹妹",而是被惡意微博吸粉。
所以,為了防止網站被釣魚,可以使用window.top來防止你的網頁被iframe.
//iframe2.html if(window != window.top){ window.top.location.href = correctURL; }
這段代碼的主要用途是限定你的網頁不能嵌套在任意網頁內。如果你想引用同域的框架的話,可以判斷域名。
if (top.location.host != window.location.host) { top.location.href = window.location.href; }
當然,如果你網頁不同域名的話,上述就會報錯。
所以,這里可以使用try...catch...進行錯誤捕獲。如果發生錯誤,則說明不同域,表示你的頁面被盜用了。可能有些瀏覽器這樣寫是不會報錯,所以需要降級處理。
這時候再進行跳轉即可.
try{ top.location.hostname; //檢測是否出錯 //如果沒有出錯,則降級處理 if (top.location.hostname != window.location.hostname) { top.location.href =window.location.href; } } catch(e){ top.location.href = window.location.href; }
這只是瀏覽器端,對iframe頁面的權限做出相關的設置。 我們還可以在服務器上,對使用iframe的權限進行設置.
X-Frame-Options
X-Frame-Options是一個相應頭,主要是描述服務器的網頁資源的iframe權限。目前的支持度是IE8+(已經很好了啊喂)有3個選項:
DENY:當前頁面不能被嵌套iframe里,即便是在相同域名的頁面中嵌套也不允許,也不允許網頁中有嵌套iframe SAMEORIGIN:iframe頁面的地址只能為同源域名下的頁面 ALLOW-FROM:可以在指定的origin url的iframe中加載
- X-Frame-Options: DENY
- 拒絕任何iframe的嵌套請求
- X-Frame-Options: SAMEORIGIN
- 只允許同源請求,例如網頁為 foo.com/123.php,則 foo.com 底下的所有網頁可以嵌入此網頁,但是 foo.com 以外的網頁不能嵌入
- X-Frame-Options: ALLOW-FROM http://s3131212.com
- 只允許指定網頁的iframe請求,不過兼容性較差Chrome不支持
X-Frame-Options其實就是將前端js對iframe的把控交給服務器來進行處理。
//js if(window != window.top){ window.top.location.href = window.location.href; } //等價於 X-Frame-Options: DENY //js if (top.location.hostname != window.location.hostname) { top.location.href =window.location.href; } //等價於 X-Frame-Options: SAMEORIGIN
該屬性是對頁面的iframe進行一個主要限制,不過,涉及iframe的header可不止這一個,另外還有一個Content Security Policy, 他同樣也可以對iframe進行限制,而且,他應該是以后網頁安全防護的主流。
CSP之頁面防護
和X-Frames-Options一樣,都需要在服務器端設置好相關的Header. CSP 的作用, 真的是太大了,他能夠極大的防止你的頁面被XSS攻擊,而且可以制定js,css,img等相關資源的origin,防止被惡意注入。不過他的兼容性,也是渣的一逼。目前支持Edge12+ 以及 IE10+。
而且目前市面上,流行的是3種CSP頭,以及各種瀏覽器的兼容性
使用主要是在后端服務器上配置,在前端,我們可以觀察Response Header 里是否有這樣的一個Header:
Content-Security-Policy: default-src 'self'
這就表明,你的網頁是啟用CSP的。通常我們可以在CSP后配置各種指定資源路徑,有
default-src, script-src, style-src, img-src, connect-src, font-src, object-src, media-src, sandbox, child-src, ...
如果你未指定的話,則是使用default-src規定的加載策略.
默認配置就是同域: default-src "self".
這里和iframe有一點瓜葛的就是 child-src 和 sandbox.
child-src就是用來指定iframe的有效加載路徑。其實和X-Frame-Options中配置allow-origin是一個道理。不過,allow-origin 沒有得到廠商們的支持。
而,sandbox其實就和iframe的sandbox屬性(下文介紹),是一樣一樣的,他可以規定來源能夠帶有什么權限.
來個demo:
Content-Security-Policy: child-src 'self' http://example.com; sandbox allow-forms allow-same-origin
此時,iframe的src就只能加載同域和example.com頁面。 最后再補充一點: 使用CSP 能夠很好的防止XSS攻擊,原理就是CSP會默認escape掉內聯樣式和腳本,以及eval執行。但是,你可以使用srcipt-src進行降低限制.
Content-Security-Policy: script-src 'unsafe-inline'
如果想更深入的了解CSP,可以參閱:CSP,中文CSP,H5rock之CSP
ok, 上面基本上就是防止自己頁面被嵌套而做的一些安全防護工作。 當然,我們面臨的安全問題還有一個,就是當iframe別人的頁面時,我們需要對其進行安全設限,雖然,跨域時iframe的安全性會大很多,但是,互聯網是沒有安全的地方。在以前,我們會進行各種trick來防止自己的頁面被污染,現在h5提供的一個新屬性sandbox可以很好的解決這個問題。
sandbox
sandbox就是用來給指定iframe設置一個沙盒模型限制iframe的更多權限.
sandbox是h5的一個新屬性,IE10+支持(md~).
啟用方式就是使用sandbox屬性:
<iframe sandbox src="..."></iframe>
這樣會對iframe頁面進行一系列的限制:
1. script腳本不能執行 2. 不能發送ajax請求 3. 不能使用本地存儲,即localStorage,cookie等 4. 不能創建新的彈窗和window 5. 不能發送表單 6. 不能加載額外插件比如flash等
看到這里,我也是醉了。 好好的一個iframe,你這樣是不是有點過分了。 不過,你可以放寬一點權限。在sandbox里面進行一些簡單設置
<iframe sandbox="allow-same-origin" src="..."></iframe>
常用的配置項有:
配置 | 效果 |
---|---|
allow-forms | 允許進行提交表單 |
allow-scripts | 運行執行腳本 |
allow-same-origin | 允許同域請求,比如ajax,storage |
allow-top-navigation | 允許iframe能夠主導window.top進行頁面跳轉 |
allow-popups | 允許iframe中彈出新窗口,比如,window.open,target="_blank" |
allow-pointer-lock | 在iframe中可以鎖定鼠標,主要和鼠標鎖定有關 |
可以通過在sandbox里,添加允許進行的權限.
<iframe sandbox="allow-forms allow-same-origin allow-scripts" src="..."></iframe>
這樣,就可以保證js腳本的執行,但是禁止iframe里的javascript執行top.location = self.location。
哎,其實,iframe的安全問題還是超級有的。比如location劫持,Refers檢查等。 不過目前而言,知道怎么簡單的做一些安全措施就over了,白帽子們會幫我們測試的。
resolve iframe跨域
iframe就是一個隔離沙盒,相當於我們在一個頁面內可以操控很多個標簽頁一樣。如果踩坑的童鞋應該知道,iframe的解決跨域也是很有套套的。
首先我們需要明確什么是跨域。
瀏覽器判斷你跨沒跨域,主要根據兩個點。 一個是你網頁的協議(protocol),一個就是你的host是否相同,即,就是url的首部:
window.location.protocol +window.location.host
需要強調的是,url首部必須一樣,比如:二級域名或者IP地址,都算是跨域.
//域名和域名對應ip, 跨域 http://www.a.com/a.js http://70.32.92.74/b.js //統一域名,不同二級域名。 跨域 http://www.a.com/a.js http://a.com/b.js
對於第二種方式的跨域(主域相同而子域不同),可以使用iframe進行解決。
在兩個不同子域下(某一方使用iframe嵌套在另一方),
即:
http: //www.foo.com/a.html和http: //script.foo.com/b.html
兩個文件中分別加上document.domain = ‘foo.com’,指定相同的主域,然后,兩個文檔就可以進行交互。
//b.html是以iframe的形式嵌套在a.html中 //www.foo.com上的a.html document.domain = 'foo.com'; var ifr = document.createElement('iframe'); ifr.src = 'http://script.foo.com/b.html'; ifr.style.display = 'none'; document.body.appendChild(ifr); ifr.onload = function(){ var doc = ifr.contentDocument || ifr.contentWindow.document; // 在這里操縱b.html alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue); }; //script.foo.com上的b.html document.domain = 'foo.com';
默認情況下document.domain 是指window.location.hostname. 你可以手動更改,但是最多只能設置為主域名。 通常,主域名就是指不帶www的hostname, 比如: foo.com , baidu.com 。 如果,帶上www或者其他的前綴,就是二級域名或者多級域名。通過上述設置,相同的domain之后,就可以進行同域的相關操作。另外還可以使用iframe和location.hash,不過由於技術out了,這里就不做介紹了。