■ 河南 郭建偉
可以說,會話ID的作用極為關鍵,正因為該會話ID的重要性,因此也成了黑客“關注”的目標。
如果某合法用戶的會話ID被黑客獲取,黑客就會偽裝成該用戶來非法訪問Web應用,這種攻擊手段被稱為會話劫持。
因此,對于會話ID進行保護就顯得極為重要。黑客獲取會話ID的方法包括預測會話ID、竊取會話ID和挾持會話ID等。
對于第一種攻擊方式來說,黑客可以采取猜測的方法來獲知會話ID。
對于第二種攻擊方式來說,黑客可以嗅探HTTP明文信息來獲取會話ID。
當然,黑客還可能會利用XSS跨站腳本,以及HTTP消息頭注入,或者將會話ID嵌入到URL等手段,來竊取會話ID。
對于第三種攻擊方式來說,黑客可以先獲取一個屬于自己的會話ID,之后便強制其他用戶使用該ID來連接Web應用。即黑客通過各種欺騙手段,將指定的會話ID強制設置到用戶的瀏覽器之中,然后就可以輕松掌控用戶的會話ID,以造成會話劫持,這也被稱為固定會話攻擊。
對于預測會話ID來說,其實是一個Web設計上的缺陷。如果生成會話ID的方法不完善,用戶的會話ID就很可能被黑客成功預測,黑客進而就可以劫持會話。
例如,基于連續的數值、固定的日期時間,以及用戶名稱等方式來產生會話ID的話,就會造成安全隱患。此外,使用一些開源軟件來生成會話ID的話,因為對用的程序邏輯實際上處于開放狀態,因此黑客根據公開的代碼也完全可以推測出會話ID。
因此,必須使用絕對的隨機數來生成會話ID,為了避免可預測的會話ID,應該避免自行開發相關的會話管理機制。最穩妥的辦法是使用成型的框架(例如,PHP、Java/J2EE、ASP.NET等編程語言或者中間件)提供的會話管理機制,來創建完全隨機的會話ID。對于預測會話ID漏洞而言,其影響的范圍包括使用會話的所有頁面,尤其對于顯示隱私信息或者執行關鍵處理(例如,購物、發帖、更改密碼等)的頁面來說,其危害尤為明顯。
注意,該攻擊方式是無需用戶參與的。具體的應對方法也很簡單,即不要自行設計會話管理機制,必須使用功能強大的Web應用開發工具內置的會話管理機制。對于此類機制來說,會將用戶的ID、IP地址、日期和時間以及隨機數等內容組合起來使用,執行加密或者散列函數處理,來得到會話ID,其安全性較高,往往是難以預測的。
黑客可以使用各種方法來竊取會話ID,例如,對于會話ID嵌入URL來說,會話ID并不保存在Cookie中,而是保存在URL中。PHP、Jave以及ASP.NET等工具都支持該功能。此外,在手機中也可能采用該方法來訪問Web應用。
但是,該方式存在很大的安全隱患,可能造成會話ID經由Referer消息頭泄露。例如,黑客可先在侵入某個合法的網站,之后在其中添加惡意鏈接指向非法網站。
而當合法的用戶點擊該惡意鏈接時,用戶當前的URL中的會話ID就會被發送給該非法網站。這樣,黑客就可以很輕松地讀取該非法網站收集的會話ID信息。
當然,由Referer造成的會話ID泄露可能是偶發事件而觸發,也可能是黑客有意為之。為了防止由此引發的偽裝攻擊,需要在Web程序中禁止將會話ID嵌入到URL中。

注意,該攻擊方式需要用戶參與。例如,對于PHP來說,執行“vim php.ini”命令,在編輯界面中將其中的“session.use_cookies=” “session.use_only_cookies=”行的值均設置為“On”,表示僅僅將會話ID保存到Cookie中。
如果將前者設置為“On”,將后者設置為“Off”,那么表示在可以使用Cookie時,將會話ID保存到Cookie中,否則將會話ID嵌入到URL中。為了安全起見,最好使用前者的組合方式。
之后執行“service httprestart”命令,重啟Apache服務讓上述修改生效。
該方法是全局性質的針對整個網站發揮作用,如果僅僅希望在網站的某個目錄下實現上述功能,可以在該目錄下創建名為“.htaccess”的文件,并在其中輸入“php_flag session.use_cookies On” “php_flag.session.use_only_cookies On”行即可。
挾持會話ID攻擊的特點是從外部劫持會話ID,黑客會先取得會話ID,該會話ID是合法的。之后將該會話ID強制提交給給受害用戶,再讓受害用戶登錄黑客需要攻擊的Web應用,最后黑客使用該會話ID順利進入目標應用。
例如,PHP網站如果存在會話ID嵌入URL漏洞,黑客可以在提交URL時,隨意指定一個會話ID來進行攻擊。
因為PHP存在會話采納機制,能夠接受來源不明的會話ID。而對于ASP.NET來說,也存在會話采納機制。對于不存在會話采納機制的中間件上運行的Web程序程序,當黑客對其進行攻擊時,會先瀏覽目標Web應用,來取得有效的會話ID,之后利用該會話ID來布設惡意鏈接來欺騙用戶。
因此,不管開發工具中是否存在會話采納機制,都不能完全避免固定會話攻擊。
根據其攻擊步驟來看,最好的防御方法是在用戶登錄時更換其會話ID,這樣黑客即使按照上述步驟行動,也無法得到用戶登錄后的真實會話ID。
例如,對于PHP來說,就可以使用“session_regenerate_id”函數,來執行更改會話ID操作,比如在認證后的網頁代碼中添加“session_regenerate_id(true)”行,來生成全新的會話ID,刪除老的會話ID,其中的“true”蠶食用來指定是否將變更前的會話ID對應的會話信息刪除。
之后再將用戶提交的信息,例如用戶名、密碼和郵箱等信息寫入到對應的會話變量中。因為老的會話ID已經消失,所以黑客發起的固定會話ID攻擊就失敗了。
對于有些Web應用來說,因為其使用的開發工具的原因,無法在程序中顯式的更改會話ID,所以可以使用令牌來防范固定會話攻擊。
其實現方法是在登錄時生成一個隨機數字字符串(即令牌),將其保存到Cookie和會話變量中,之后在各頁面進行認證時比較上述令牌值,如果相符就視為已認證狀態,否則視為認證錯誤。
因為只有在登錄時,令牌才可以被傳到外界,黑客無法得知該令牌,所以使用令牌可以有效防御固定會話攻擊。例如,在網頁代碼中添加如下命令,設置產生隨機數的函數:

之后,添加“$token=getToken()”行,來產生隨機數(即令牌)。添加“setcookie('token',$token,0,'/');” “$_SESSION ['token']=$token;”行,將令牌保存到Cookie和會話變量中。
這樣,合法用戶可以利用Cookie來獲取該令牌。之后可以利用該令牌進行身份驗證。
例如在對應的頁面中添加:

就可以執行令牌比對操作,即從用戶提交的Cookie中取得令牌,和會話變量中讀取的令牌進行比對,如果一致則說明用戶合法。黑客雖然可以利用固定會話進行攻擊,但是無法得到該令牌,所以無法進行有效的身份驗證操作。
而對于有些Web網站(尤其是購物網站)可能在登錄前就使用了會話變量,在這種情況下,要想完全防御固定會話攻擊是比較困難的。比較穩妥的對策是,在登錄前不要使用會話管理機制,而使用Hidden參數來傳遞值。
當然,為了更好地提高安全性,可以采取各種方式來加以防范,例如,不要在登錄前的會話變量中保存敏感信息,不使用嵌入會話ID的URL,不要使用地域型域名等。
