歡迎光臨
每天分享高質量文章

小心 !跨站點websocket劫持!

 來自:碼農翻身(微訊號:coderising)

 

開始之前,先熱熱身,講個小故事:

 

年終獎下來了,張大胖琢磨著去買點兒股票作為投資,他用瀏覽器訪問了www.stock.com , 輸入了使用者名稱和密碼,登入成功。

 

stock.com傳回了cookie用來標識張大胖這個使用者。

 

 

瀏覽器認真負責, 它把這個Cookie記錄了下來,以後張大胖每一次再向stock.com發起Http請求,瀏覽器都會兢兢業業地把Cookie加入到Http請求的Header中,一併發到stock.com ,  這樣stock.com就知道張大胖已經登陸過了,就可以按照張大胖的請求來做事情,比如檢視股票,買賣股票。

 

張大胖看到股票漲幅不錯,心中暗喜。 他又開啟了www.beauty.com, 去看一些自己的小秘密。

 

瀏覽器把beauty.com的HTML,JavaScript都下載到本地,開始執行。

 

這個JavaScript中建立了一個XMLHttpRequest物件,然後居然向stock.com發起了HTTP請求 !

 

瀏覽器嚴格按照規定,把之前儲存的cookie也新增到Http請求中 !

 

無辜的stock.com根本不知道這個Http請求是beauty.com的JavaScript發出的,還是張大胖發出的

 

stock.com 檢查了cookie,就知道這是一個登入過的使用者,於是就冷冰冰地去執行,張大胖的個人資訊就洩露了。

 

(當然,實施這樣一次攻擊不會這麼簡單,這裡只是說明基本原理)

 

可憐的張大胖就是因為瀏覽了一個網站,就遭受了錢財損失。 這也太可怕了!

 

我們來複盤一下為什麼會發生這種情況, 主要有兩個原因:

 

首先,每當訪問stock.com的時候(不管是人點選按鈕/連結,或者是透過程式的方式),儲存在瀏覽器的stock.com的cookie都會發過去。

 

其次,從beauty.com下載的JS利用XMLHttp訪問了stock.com。

 

第一點我們是無法阻止的, 如果阻止了,cookie就沒用了。

 

對於第二點,瀏覽器必須做出限制, 不能讓來自beauty.com的JavaScript去訪問stock.com! 這個限制就是大家所熟知的同源策略

 

同源策略非常嚴格,要求兩個URL必須滿足下麵三個條件才算同源。

 

(1) 協議(http/https) 相同

(2) 域名相同

(3) 埠相同

 

(碼農翻身註:詳情參見《瀏覽器的安全反擊戰》)

 

這個要求可以說是殺敵一千,自損八百

 

因為對大的系統來說,有很多域名是很正常的事情,現在JavaScript只能向自己的“源”發起請求,不能訪問別的系統,這實在是太讓人難受了。

 

於是人們想了很多辦法,比如JSONP , CORS等來突破這個限制。

 

等到websocket這個新的技術出現以後,乾脆放棄了這個限制,websocket可以跨域訪問

 

但是這就帶來的安全隱患: 跨站點websocket 劫持 ,  我們接著張大胖的故事往下講。

跨站點websocket 劫持

張大胖又一次登入了www.stock.com, 瀏覽器又收到了cookie並且儲存了下來, 這一次張大胖發現stock.com提供了一個新功能: 實時的股票價格推送。

 

張大胖開啟了這個新功能,這是用websocket實現的。 大家都知道,websocket的通訊是由HTTP協議發起的。 

 

瀏覽器向stock.com發起了一個HTTP請求, 這個請求希望把HTTP 協議升級為web socket協議,下麵是HTTP請求的Header:

 

GET /stock/ws HTTP/1.1

Host: www.stock.com

User-Agent: xxxxxx

……

Origin: https://www.stock.com

Sec-WebSocket-Key: xxxxx

Cookie: JSESSIONID=2B323FCF3968ETDSA9459

Connection: keep-alive, Upgrade

Upgrade: websocket

 

註意,Cookie資料也傳送給了stock.com

 

stock.com檢查Cookie,確認是個登陸過的客戶,於是建立websocket連線,並且推送張大胖訂閱的最新的股票資訊。

 

張大胖看到最新的股票資訊,很高興,他又開啟了www.beauty.com, 去看一些自己的小秘密。

 

這個beauty.com中的JavaScript又一次執行,也向stock.com發起HTTP請求,也要建立websocket連線。

 

GET /stock/ws HTTP/1.1

Host: www.stock.com

User-Agent: xxxxxx

……

Origin: https://www.beauty.com

Sec-WebSocket-Key: xxxxx

Cookie: JSESSIONID=2B323FCF3968ETDSA9459

Connection: keep-alive, Upgrade

Upgrade: websocket

 

stock.com收到請求,檢查Cookie,確認是個登陸過的客戶,也成功地建立了websocket連線, 把資料也推送給你beauty.com , 於是張大胖的資訊就暴漏了。 

 

如果這個websocket還支援別的操作,那危害就更大了。(這也是被稱為“劫持”,而不僅僅是“偽造”的原因)

 

可以看出,websocket不遵守同源策略,是導致跨站點指令碼劫持的最大原因。

 

Websocket協議怎麼解決這個問題呢?

 

敏銳的同學已經註意了,在前面的HTTP請求中,有個叫做Origin的東西:

 

合法請求:

Origin:https://www.stock.com

 

攻擊請求:

Origin:https://www.beauty.com

 

這個Origin是websocket協議所要求的。 

 

所以在www.stock.com的伺服器端,在建立websocket連線的時候,一定要去檢查這個Origin,確保這個Origin在自己的白名單中

幾個小問題

1、不就是一個Origin嗎? 駭客可以輕鬆地偽造啊?

 

註意:這一切都發生在張大胖的瀏覽器中,是張大胖在操作, 駭客想偽造的話,只能透過JavaScript來修改它。

 

但是協議規定: 這個Origin是在HTTP Header中, 是由瀏覽器自動加上的不能透過程式設計的方式(如JavaScript)來改變它

 

2、那駭客可以修改HTTP請求,把這個Origin改了啊?

 

如果你控制了張大胖的瀏覽器,甚至張大胖的電腦,那肯定可以修改HTTP請求, 但是都控制電腦了,一切盡在掌握,還費這勁幹嘛,直接監控使用者名稱和密碼不就得了。

 

如果你充當中間人,透過抓包的方式,來修改Origin,那確實可以,這時候張大胖需要用Https,和wss來防範了。

 

3、還有沒有別的辦法來防範?

 

有的,還有個更加安全的辦法,和防範CSRF的思想是一致的: 使用token 。

 

(1) 伺服器端給每個websocket客戶端分配一個隨機的,唯一的token

(2) 瀏覽器在建立websocket連線的時候,把token也發過來。

(3) 伺服器端驗證token, 如果有效,才建立連線,並且廢棄掉這個token。

    贊(0)

    分享創造快樂