一個跨域請求的XSS漏洞


    場景回顧

    一個表單進行跨域提交的方式有很多,我們使用的采用隱藏iframe,在本域下放一個代理頁面,通過服務端配合完成一次完整的請求。

    首先,部署proxy.html代理頁面。這個頁面處理服務端返回的數據,並執行接口的回調函數。接口請求成功后,返回的是:

<script>location.href='http://www.a.com/proxy.html?fun=callback&a=1&b=2&c=3';</script>

    proxy頁面,解析服務端傳回的參數最后執行: 

callback({

        a:1,

        b:2,

        c:3

    });

    這樣就完成了一次,接口請求並且在請求成功后,執行回調。

    其次,頁面上需要有一個隱藏的iframe,把請求發到這個頁面,然后接受返回值。

    整體上是這么一個過程,實現了post請求的跨域提交。 

    proxy.html的代碼:

<!doctype html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><script type="text/javascript">
(function(){
		var queryStr = location.search.substring(1).split('&'),oneQueryStr,args = {},g = top,scope = top ,callback;
		for(var i in queryStr){
			oneQueryStr = queryStr[i].split('=');
			if(!callback && oneQueryStr[0] == 'fun'){
				callback = oneQueryStr[1];
			};
			if(oneQueryStr[0]&&oneQueryStr[1]){
				args[oneQueryStr[0]] = (oneQueryStr[1]||'').replace(/[><'"{}]/g, '');
			}

		}
		callback = callback.split('.');

		if( callback[0] === 'document' 
			|| callback[0] === 'location' 
			|| callback[0] === 'alert'){
		}else{
			for(var i = 0,len= callback.length;i<len;i++){
				if(i==0 && callback[0]=="parent"){
					g = parent;
					scope = parent;
				}else if(i==0 && callback[0]=="top"){
					g = top;
					scope = top;
				}else{
					if(i<len-1){
						scope = scope[callback[i]];
					}
					g = g[callback[i]];
				}
			}

			g.call(scope,args);
		}
	
})();
</script>
</body></html>

    XSS漏洞

    很顯然,既然頁面上執行了接口返回的數據。那么就必須對返回的數據進行過濾,這樣才能防止惡意的代碼進行攻擊。

    看了上面proxy.html的代碼我們發現,已經處理了fun這個參數的值,不能為alert、document、location這些值。這是通過黑名單機制來進行判斷的,一旦命中就無法執行。但是一直存在這么一個問題:我們能防的只是我們所了解的XSS漏洞,如果我們不知道,就需要遇到問題,解決問題,這樣顯然很被動。 

    有這么一個攻擊案例,即便是我們已經過濾了alert、document這些window下的方法,但是還有我們不知道的方法無法防御,這就增大了我們的維護成本。在我們業務里,帶來的問題是:每次調整這個文件,整個公司的業務可能都會被牽扯進來,都要升級很被動。

    上面的這個例子就是掉用了頁面上給window下擴展的$,這個變量對於前端的同學都不陌生。這個$能干的事情就更多了,簡直太可怕了。這個案例只是打印了你的cookie,他可以做很多很多的事情,后果可以預想...

    解決方案

    還是要過濾fun參數,這個『萬惡之源』,采用的方式的白名單+黑名單,雙層防護。首先使用白名單進行過濾,白名單設置的是業務所用的函數名,其他的都不信任;其次,白名單如果驗證通過后,在進行黑名單驗證。為什么還需要這么異步操作呢?主要的擔心有這么一個方法,白名單會通過,但是又是無用的方法,這樣就可以使用黑名單在此過濾。       

    后續跟進 

    我現在的這個處理方式不一定是最好的,也可能存在問題。在這里提出,有兩方面的考慮。其一:想要獲得更好的方案來解決這個問題;其二:攻擊和防守是一個持續的問題,需要一直跟進,逐漸找到合理的解決方案。如果有更好的方案,也希望不吝賜教!

 

 

 


免責聲明!

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



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