# DOM-based Lab6 這題是 DOM Clobbering XSS 漏洞,利用了 JavaScript 中的邏輯錯誤 + HTML DOM 行為 + 技巧來觸發 alert()。 所以一樣先進入網站。 ![image](https://hackmd.io/_uploads/B1HalzREex.png) 然後到文章下面留言: ```html <a id=defaultAvatar></a><a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//"></a> ``` - 建立兩個 `<a>` 元素,`id=defaultAvatar` - 第二個還多了一個 `name=avatar`(這會覆寫 avatar 屬性) - `href="cid:&quot;onerror=alert(1)//"` 裡的 `&quot;` 會在 DOM 中還原成 `"`,構造出完整的 payload。 完成本題 DOM Clobbering 的一部分。 ![image](https://hackmd.io/_uploads/rJ_Jv70Ege.png) :::info ### DOM Clobbering 是什麼? DOM Clobbering 是利用 HTML 元素的 `name` 或 `id` 屬性來「覆寫」原本 window 或 JavaScript 中的變數名稱,進而造成邏輯錯誤或安全漏洞。 ```htmll <a name="user"></a> ``` 這會讓你在 JS 中 window.user 變成 `<a name="user">` 元素,覆蓋掉原本 user 的變數。這題我們就是用 `name="avatar"` 來 clobber 掉 defaultAvatar.avatar 的存取邏輯。 ::: 當這段 HTML 被加入後: ``` let defaultAvatar = window.defaultAvatar || {avatar: '/resources/images/avatarDefault.svg'} ``` 這行不會跑 fallback 的 object 是因為 `window.defaultAvatar` 現在是兩個 `<a>` 元素組成的 HTMLCollection,JavaScript 認為它是「truthy」。 :::info ### 為何 window.defaultAvatar 是 truthy? fallback 沒跑的原因: ``` let defaultAvatar = window.defaultAvatar || { avatar: '/default.png' } ``` 當我們塞了兩個 `<a id="defaultAvatar">` 到 HTML 中,`window.defaultAvatar` 會變成 HTMLCollection,不是 undefined,也不是 null,而是一個 **object(類陣列)**。 JavaScript 中**所有 object(不論是不是空的)都會被視為 truthy**,所以不會 fallback 成 `{ avatar: '/default.png' }`。 ::: 之後程式會用: ``` let img = document.createElement('img'); img.src = defaultAvatar.avatar; ``` 結果 defaultAvatar.avatar 取到的值是這個: ``` <a name=avatar href='cid:"onerror=alert(1)//'> ``` 這樣就構造出: ``` <img src='cid:"onerror=alert(1)//'> ``` onerror 成功觸發。 接著我們再回去隨便發的留言觸發效果: ![image](https://hackmd.io/_uploads/SJsQuX0Exl.png) Bang。 ![image](https://hackmd.io/_uploads/HJxwOm04gg.png) :::info ### 為何要回去留言? 這是為了讓頁面重新 render,並使用被污染的 defaultAvatar。這時候 alert(1) 就會被觸發了。 ### 盡量在 Chrome 執行 - cid: 協議(Content-ID)允許 " 在 Chrome 被正常還原、組合出 JavaScript 事件。 - Firefox 和其他瀏覽器會比較嚴格處理 src="cid:...",不會觸發 onerror。 ::: ---