Web前端安全之iframe


防嵌套網頁

比如,最出名的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中加載
  1. X-Frame-Options: DENY
  2. 拒絕任何iframe的嵌套請求
  3. X-Frame-Options: SAMEORIGIN
  4. 只允許同源請求,例如網頁為 foo.com/123.php,則 foo.com 底下的所有網頁可以嵌入此網頁,但是 foo.com 以外的網頁不能嵌入
  5. X-Frame-Options: ALLOW-FROM http://s3131212.com
  6. 只允許指定網頁的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了,這里就不做介紹了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM