整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ
Vue3 中使用 DOMPurify 避免 XSS 攻擊

前言
在 Vue 中,我們可以使用 v-html 來將 HTML 字串轉換成 DOM 元素,但是這樣會有一個問題,就是容易受到 XSS 攻擊,因為我們無法確保使用者輸入的內容是否安全,所以我們需要對使用者輸入的內容進行過濾,避免惡意的腳本被執行。
DOMPurify
在 Vue 中,總共有三種渲染資料的方式,分別是:
- mustache interpolations,也就是
{{ myName }}的方式 v-textv-html
其中,{{ myName }} 和 v-text 都是將資料轉換成純文字,而 v-html 則是將資料轉換成 HTML 元素,而這個 v-html 類似於 innerHTML,但本質上不是 innerHTML,因為 v-html 是具備雙向綁定能力的,而 innerHTML 則不具備雙向綁定能力。
See the Pen v-html by Ray (@hsiangfeng) on CodePen.
我們都知道使用 innerHTML 直接將 HTML 渲染出來是一件很危險的事情,是有可能發生 XSS 攻擊的,雖然使用 mustache interpolations or v-text 指令是可以避免這個問題存在,因為框架本身就會幫我們過濾掉 HTML 標籤,但是有時候我們還是需要使用 v-html 來渲染 HTML。
那…什麼狀況下會需要使用 v-html 呢?比較常見就是讓使用者可以輸入 HTML 內容的場景,最常見的功能就是 Editor,像是部落格、留言板等等,這時候我們就需要使用 v-html 來渲染使用者輸入的 HTML 內容。
這時候我們就可以使用 DOMPurify 來避免 XSS 攻擊,DOMPurify 是可以將危險的標籤給過濾掉的套件,所以我們可以使用 DOMPurify 來過濾掉危險的標籤,避免惡意的腳本被執行。
首先我先寫一個範例,假裝當使用者輸入了一個惡意的腳本,然後我們使用 v-html 來渲染這個腳本,看看會發生什麼事情
See the Pen v-html ajax by Ray (@hsiangfeng) on CodePen.
上方的範例是一個 Vue3 Composition API,當你點下 Get Data 的按鈕後,接著過五秒後會將資料渲染到畫面上,這時候你會發現畫面上出現了一個 Image 的標籤,但是這個標籤卻是一個惡意的腳本,因為這個標籤的圖片並不會出現,因此就會觸發了 onerror 事件,接著就會執行 alert,這就是一個 XSS 攻擊。
那我們要怎麼避免這個問題呢?前面有提到我們將會使用 DOMPurify 來過濾掉危險的標籤,所以安裝方式有兩種,一種是使用 npm 安裝,另一種是使用 CDN,這邊為了方便使用以及介紹,所以我會使用 CDN 的方式
1 | |
底下我也提供一個範例 CodePen,方便你可以 Fork 回家使用:
See the Pen v-html ajax XSS by Ray (@hsiangfeng) on CodePen.
那麼該如何使用 DOMPurify 呢?其實非常簡單,你只需要使用 sanitize 這個方法,然後將你要過濾的 HTML 字串傳入,就可以得到一個過濾過的 HTML 字串,接著你就可以使用 v-html 來渲染這個字串,這樣就可以避免 XSS 攻擊了
See the Pen v-html DOMPurify by Ray (@hsiangfeng) on CodePen.
上方範例你可以發現當你點下 Get Data 按鈕後,雖然還是會出現死圖,但是卻不會觸發 onerror 事件,因此就不會有 XSS 攻擊的問題了,而這就是 DOMPurify 的功用。
關於 DOMPurify 其他的用法
這時候你就好奇了,那我要怎麼知道 DOMPurify 過濾掉了哪些標籤呢?其實你可以使用 DOMPurify.removed 來得知,這個屬性會回傳一個陣列,裡面包含了被過濾掉的標籤,這樣你就可以知道 DOMPurify 到底過濾掉了哪些標籤了。
1 | |

我們可以看到陣列中包含了一個物件,然後物件中有兩個屬性,分別是
attribute:被過濾掉的屬性from:被過濾後的 HTML 標籤
但要稍微注意一下 DOMPurify.removed 這屬性只是讓你看一下而已,如官方文件所說,請不要使用這個屬性作為你的程式邏輯。
通常我們實戰開發上一定不會通通過濾掉,可能會有一些標籤是可以被接受的,這時候我們就可以使用 DOMPurify.sanitize 來自訂過濾的規則,這個方法可以接受兩個參數,分別是:
dirty:要過濾的 HTML 字串config:過濾的規則
那麼這部分就滿多的,我就不多做介紹建議直接觀看 官方文件 為主哩~
什麼時候該使用 DOMPurify?
其實使用的場景比較常見於,資料是由使用者輸入的,像是 Editor、留言板等等,如同前面所講的,現今的框架都具備基本的 XSS 防禦機制,並且我們將資料儲存到資料庫時,後端也會對資料進行過濾。
那竟然後端以及前端框架都有防禦機制,那我們還需要使用 DOMPurify 嗎?其實這取決於使用場景,以 Vue 來講,如果你渲染資料的方式是使用 {{ myName }} 或是 v-text,那其實就不需要使用 DOMPurify 了,因為 Vue 會幫你過濾掉 HTML 標籤,但是如果你使用 v-html 來渲染資料,那就需要使用 DOMPurify 來過濾掉危險的標籤。
所以簡單來講,如果你的功能如果是需要直接渲染 HTML 字串,那就會建議你在前端使用 DOMPurify 來過濾掉危險的標籤,這樣子就可以避免惡意的腳本被執行哩
整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ