Session固定攻擊(Session Fixation)
-
對象:程式設計師/資訊安全人員
-
難易度:★★☆☆☆
-
技術新舊:
-
閱讀所需時間:10~20分鐘
預備知識
-
熟悉php、session處理機制
簡介
HTTP是一種stateless的通訊協定,是用來展示內容而不是記錄資訊,因此使用者對伺服器所進行的操作並不會被保存起來。為了克服這個問題,網路應用程式或者伺服器採用各種不同的session機制。其背後最基本的觀念是server會產生一Session ID(SID),並將SID回傳給瀏覽器。當使用者之後進行請求時,確保相同的SID會跟隨請求發送,如此server就能用SID來紀錄使用者相關的操作。
Session的防護重心通常是放在防止session被攔截、猜測或者暴力破解。我們可以透過使用加密的通訊、強健的加密演算法跟足夠長度的session來防止。但當攻擊者透過指定的方式將Session ID指派給使用者的瀏覽器,迫使使用者使用被指定的session,那麼即使sessioin並沒有被攔截、猜測或者暴力破解,攻擊者仍能取得session值。這種攻擊手法我們稱為”session fixation”,因為session的值並不是在使用者登入時隨機產生,而是在事先就已經被指定了。
攻擊情境
基本的攻擊情境
-
攻擊者登入網站(攻擊者須先為網站的會員),如 http://unsafebank.com/。
-
網站指定一Session ID給攻擊者,如1234。
-
攻擊者發送一含有 http://unsafebank.com/login.php?sid=1234的超連結給受害者。
-
受害者點選連結後,連結到網站的登入頁面。
-
因為這個連結含有?sid=1234,網站不會重新產生一個新的session ID值。
-
使用者成功登入後,攻擊者便可使用 http://unsafebank.com/account.php?sid=1234來存取受害者的帳戶。
這個方法的缺點在於攻擊者必須為網站的會員,且需要使用者點選連結後登入才能讓session固定。這種方法事實上並不太採用,在這裡只是做為說明攻擊者的目的在於設法讓session值能固定。
攻擊者固定使用者的Session ID方法
-
方法一:Session ID透過URL參數指定
如上述例子,攻擊者試圖讓受害者點選他所提供的超連結,如http://unsafebank.com/login.php?sid=1234。
-
方法二:Session ID由表單隱藏欄位指定
攻擊者會設法讓受害者填寫含有指定session ID的登入表單,可能是使用仿造的網站或者利用Cross-site scripting弱點。
-
方法三:Session ID由Cookie傳送
攻擊者要設法在受害者的瀏覽器設定含有Session ID的cookie。常見方法如下:
-
使用客戶端程式語言指定cookie值
透過XSS的漏洞,設定document.cookie值。如 http://unsafebank.com/<script>document.cookie=“sessionid=1234”;</script>
-
使用<meta>標籤來設定cookie
伺服器可以在回應的Http標頭裡使用<meta>的標籤來設定瀏覽器的cookie值,如<meta http-equiv=Set-Cookie content=“sessionid=1234”>。攻擊者可透過Meta tag injection來達成這個目的。
-
使用set-cookie來設定cookie
想辦法在回應的http標頭裡包含Set-cookie的header
防範方法
1、不要接受由GET或者POST變數指定的SID值
由URL或者POST變數來取得SID會讓發生此種攻擊的機會大幅的提升,產生連結或者表單來指定這些變數是相當容易的。
2、針對每一請求重新產生SID
針對每一請求重新產生Session ID,那麼即使攻擊者能誘使受害者使用已知的session ID進行登錄,當攻擊者想要使用受害者的Session登入時便無法進行操作。例如:
如果Bob成功的讓Alice點選http://unsafebank.com/?sid=1234,那麼這個請求的header如下:
GET /?SID=1234/1.1
Host: Alice
但因為server會重新產生新的Session ID,而這個Session ID只有Alice知道,所以Bob知道的Session ID也無法再拿來操作。
HTTP/1.1 200 OK
Set-Cookie: SID=3134998145AB331F
3、只接受server產生的Session ID
if (!isset($_SESSION['SERVER_GENERATED_SID'])) {
session_destroy(); // destroy all data in session
}
session_regenerate_id(); // generate a new session identifier
$_SESSION['SERVER_GENERATED_SID'] = true;
4、為Session ID訂定一Time-Out時間
針對每一Session ID值,儲存一session變數表示上次這個SID進行存取的timestamp。當這個sid被再次使用時,與這個timestamp進行比較。若是二者的差異在一定義好的時間差內(例如十分鐘),則更新這個timestamp的值,否則便刪除這個SID。這個方法很容易實作且能防範未授權的使用者試圖透過相同的電腦能存取授權使用者的帳戶。
5、如果Refer的來源是可疑的,刪除Session
當你在拜訪某一頁面時,browser會紀錄你是從何連到這個頁面,也就是Refer。當使用者連結到某一網站時,如果這個網頁不太可能是由其他網頁連結過來,或者使用者不太可能長時間都在這個網頁保持登入狀態時,refer便應該為此網頁。其他的Refer便應視為可疑的。舉例來說:
if (strpos($_SERVER['HTTP_REFERER'], 'http://vulnerable/') !== 0) {
session_destroy(); // destroy all data in session
}
session_regenerate_id(); // generate a new session identifier
6、用戶代理
瀏覽器透過”User-Agent”的HTTP 標頭來辨認自己。這個標頭在正常使用下通常不會改變。如果這個header被改變了,那麼就相當可疑。一個網路應用程式可以透過偵測User-Agent是否改變來防止惡意使用者偷取Session.
if ($_SERVER['HTTP_USER_AGENT'] !== $_SESSION['PREV_USERAGENT']) {
session_destroy(); // destroy all data in session
}
session_regenerate_id(); // generate a new session identifier
$_SESSION['PREV_USERAGENT'] = $_SERVER['HTTP_USER_AGENT'];
作者列表
2009/11/02 王奕翔 初稿
參考資料
http://en.wikipedia.org/wiki/Session_fixation
http://www.acrossecurity.com/papers/session_fixation.pdf