XSS跨站指令碼攻擊
一、簡介
跨站指令碼(cross site script)為了避免與樣式css混淆,所以簡稱為XSS。
XSS是指惡意攻擊者利用網站沒有對使用者提交資料進行轉義處理或者過濾不足的缺點,進而新增一些程式碼,嵌入到web頁面中去。使別的使用者訪問都會執行相應的嵌入程式碼。
從而盜取使用者資料、利用使用者身份進行某種動作或者對訪問者進行病毒侵害的一種攻擊方式。
XSS是一種經常出現在web應用中的電腦保安漏洞,也是web中最主流的攻擊方式。
二、原因解析
主要原因:過於信任客戶端提交的資料!
解決辦法:不信任任何客戶端提交的資料,只要是客戶端提交的資料就應該先進行相應的過濾處理然後方可進行下一步的操作。
進一步分析細節:
客戶端提交的資料本來就是應用所需要的,但是惡意攻擊者利用網站對客戶端提交資料的信任,在資料中插入一些符號以及javascript程式碼,那麼這些資料將會成為應用程式碼中的一部分了。那麼攻擊者就可以肆無忌憚地展開攻擊啦。
因此我們絕不可以信任任何客戶端提交的資料!!!
三、XSS攻擊分類
1、反射型xss攻擊
又稱為非永續性跨站點指令碼攻擊,它是最常見的型別的XSS。漏洞產生的原因是攻擊者注入的資料反映在響應中。一個典型的非永續性XSS包含一個帶XSS攻擊向量的連結(即每次攻擊需要使用者的點選)。
2、存貯型xss攻擊
又稱為持久型跨站點指令碼,它一般發生在XSS攻擊向量(一般指XSS攻擊程式碼)儲存在網站資料庫,當一個頁面被使用者開啟的時候執行。每當使用者開啟瀏覽器,指令碼執行。持久的XSS相比非永續性XSS攻擊危害性更大,因為每當使用者開啟頁面,檢視內容時指令碼將自動執行。
3、DOMBasedXSS(基於dom的跨站點指令碼攻擊)
基於DOM的XSS有時也稱為type0XSS。當用戶能夠通過互動修改瀏覽器頁面中的DOM(DocumentObjectModel)並顯示在瀏覽器上時,就有可能產生這種漏洞,從效果上來說它也是反射型XSS。
通過修改頁面的DOM節點形成的XSS,稱之為DOMBasedXSS
前提是易受攻擊的網站有一個HTML頁面採用不安全的方式從document.location 或document.URL 或 document.referrer獲取資料(或者任何其他攻擊者可以修改的物件)。
四、XSS漏洞修復
XSS漏洞的起因就是沒有對使用者提交的資料進行嚴格的過濾處理。因此在思考解決XSS漏洞的時候,我們應該重點把握如何才能更好的將使用者提交的資料進行安全過濾。
1、html實體
在html中有些字元,像(<)這類的,對HTML(標準通用標記語言下的一個應用)來說是有特殊意義的,所以這些字元是不允許在文字中使用的。要在HTML中顯示(<)這個字元,我們就必須使用實體字元。
html實體的存在是導致XSS漏洞的主要原因之一。
因此我們需要將這些實體全部轉換為相應的實體編號。
2、HTML Encode
使用者將資料提交上來的時候進行HTML編碼,將相應的符號轉換為實體名稱再進行下一步的處理。
3、修復漏洞方針
1、將重要的cookie標記為http only, 這樣的話Javascript 中的document.cookie語句就不能獲取到cookie了.
2、表單資料規定值的型別,例如:年齡應為只能為int、name只能為字母數字組合。。。。
4、對資料進行Html Encode 處理
5、過濾或移除特殊的Html標籤, 例如: <script>, <iframe> , < for <, > for >, " for
6、過濾JavaScript 事件的標籤。例如 "onclick=", "onfocus" 等等。
【特別注意:】
在有些應用中是允許html標籤出現的,甚至是javascript程式碼出現。因此我們在過濾資料的時候需要仔細分析哪些資料是有特殊要求(例如輸出需要html程式碼、javascript程式碼拼接、或者此表單直接允許使用等等),然後區別處理!
// HTML和實體相互轉換 String.prototype.convertEntity=(function(){ // 字元實體表 let entity = { quot : '"', lt : '<', gt : '>', amp : '&', nbsp : ' ' } let entity_cover_key='',entity_cover={}; for(let item in entity){ entity_cover_key+=entity[item]; entity_cover[entity[item]]='&'+item+';'; } return function(type){ if(type == 1){ return this.replace(/&([^&;]+);/g,function(a,b){ return typeof entity[b] === 'string' ? entity[b] : a; }) }else{ let reg=new RegExp('['+entity_cover_key+']','g') return this.replace(reg,function(c){ return entity_cover[c]; }); } } })() console.log('"><& &asds;'.covert(1)); // ""><& " console.log('<div>121212</div>'.covert()); // <div>121212</div>