安全性
報告漏洞
當報告漏洞時,它立即成為我們的首要關注事項,一個全職貢獻者會放下一切來處理它。為了報告漏洞,請傳送電子郵件至 security@vuejs.org。
儘管發現新的漏洞很少,但我們也建議始終使用Vue及其官方配套庫的最新版本,以確保您的應用程式儘可能安全。
規則第1條:絕不要使用不可信的模板
使用Vue時的最基本安全規則是 絕不要將不可信內容用作元件模板。這樣做等同於允許在您的應用程式中執行任意JavaScript - 更糟糕的是,如果在伺服器端渲染期間執行程式碼,可能會導致伺服器洩露。此類使用的示例
js
Vue.createApp({
template: `<div>` + userProvidedString + `</div>` // NEVER DO THIS
}).mount('#app')
Vue模板被編譯成JavaScript,模板內的表示式將在渲染過程中執行。儘管表示式是在特定的渲染上下文中評估的,但由於潛在的全球執行環境複雜,像Vue這樣的框架完全保護您免受潛在惡意程式碼執行的可能性實際上是不切實際的,會帶來不合理的效能開銷。避免這類問題的最直接方法是確保您的Vue模板內容始終是可信的,並且完全受您控制。
Vue如何保護你
HTML內容
無論使用模板還是渲染函式,內容都會自動轉義。這意味著在這個模板中
template
<h1>{{ userProvidedString }}</h1>
如果 userProvidedString
包含
js
'<script>alert("hi")</script>'
那麼它將被轉義成以下HTML
template
<script>alert("hi")</script>
這可以防止指令碼注入。這種轉義是透過原生的瀏覽器API完成的,例如 textContent
,因此只有當瀏覽器本身存在漏洞時,才可能存在漏洞。
屬性繫結
類似地,動態屬性繫結也會自動轉義。這意味著在這個模板中
template
<h1 :title="userProvidedString">
hello
</h1>
如果 userProvidedString
包含
js
'" onclick="alert(\'hi\')'
那麼它將被轉義成以下HTML
template
" onclick="alert('hi')
這可以防止關閉 title
屬性以注入新的、任意的HTML。這種轉義是透過原生的瀏覽器API完成的,例如 setAttribute
,因此只有當瀏覽器本身存在漏洞時,才可能存在漏洞。
潛在危險
在任何Web應用程式中,允許未經過濾的使用者提供的內谷作為HTML、CSS或JavaScript執行,可能存在潛在的危險,因此應儘可能避免。儘管有時一些風險可能是可以接受的。
例如,CodePen和JSFiddle等服務允許執行使用者提供的內谷,但這是在預期並部分沙盒化的iframe環境內。當重要的功能固有的需要一定程度的漏洞時,評估該功能的重要性與漏洞可能帶來的最壞情況由您的團隊負責。
HTML注入
如您之前所學,Vue會自動轉義HTML內容,防止您不小心將可執行的HTML注入到您的應用程式中。然而,在您知道HTML是安全的情況下,您可以顯式渲染HTML內容
使用模板
template<div v-html="userProvidedHtml"></div>
使用渲染函式
jsh('div', { innerHTML: this.userProvidedHtml })
使用帶有JSX的渲染函式
jsx<div innerHTML={this.userProvidedHtml}></div>
警告
除非HTML在沙盒化的iframe中或僅在編寫該HTML的使用者可能接觸到的應用程式部分中,否則使用者提供的HTML永遠不能被認為是100%安全的。此外,允許使用者編寫自己的Vue模板也帶來了類似的風險。
URL注入
在這樣一個URL中
template
<a :href="userProvidedUrl">
click me
</a>
如果URL沒有使用 javascript:
防止JavaScript執行進行“淨化”,那麼將存在潛在的安全問題。有一些庫,例如 sanitize-url,可以幫助您完成這項工作,但請注意:如果您在客戶端進行URL淨化,那麼您已經存在一個安全問題。使用者提供的URL應在儲存到資料庫之前始終由您的後端進行淨化。這樣就可以避免每個連線到您的API的客戶端,包括原生移動應用程式的問題。另外,請注意,即使在淨化後的URL中,Vue也無法幫助您保證它們指向的是安全的目的地。
樣式注入
看看這個例子
template
<a
:href="sanitizedUrl"
:style="userProvidedStyles"
>
click me
</a>
假設 sanitizedUrl
已經被淨化,所以它肯定是一個真實的URL而不是JavaScript。有了 userProvidedStyles
,惡意使用者仍然可以提供CSS來“點選劫持”,例如將連結樣式設定為透明的框覆蓋在“登入”按鈕上。然後如果 https://user-controlled-website.com/
被構建得與您的應用程式的登入頁面相似,他們可能已經捕獲了使用者的真實登入資訊。
您可能能夠想象,允許使用者為 <style>
元素提供內容將會如何建立更大的安全漏洞,因為這會讓使用者完全控制整個頁面的樣式。這就是為什麼 Vue 阻止在模板中渲染樣式標籤,例如
template
<style>{{ userProvidedStyles }}</style>
為了確保您的使用者完全免受點選劫持,我們建議只允許在沙盒 iframe 內對 CSS 完全控制。或者,當透過樣式繫結提供使用者控制時,我們建議使用其 物件語法,並且只允許使用者為它們可以安全控制的特定屬性提供值,如下所示
template
<a
:href="sanitizedUrl"
:style="{
color: userProvidedColor,
background: userProvidedBackground
}"
>
click me
</a>
JavaScript 注入
我們強烈建議永遠不要使用 Vue 渲染 <script>
元素,因為模板和渲染函式永遠不應該有副作用。然而,這並不是唯一一種在執行時將其評估為 JavaScript 的字串的方法。
每個 HTML 元素都有接受字串的屬性值,例如 onclick
、onfocus
和 onmouseenter
。將使用者提供的 JavaScript 繫結到任何這些事件屬性上是一種潛在的安全風險,因此應該避免。
警告
除非它位於沙盒 iframe 中或在應用中只有編寫該 JavaScript 的使用者才能暴露於其中,否則使用者提供的 JavaScript 永遠不能被認為是 100% 安全的。
有時我們會收到關於如何在 Vue 模板中執行跨站指令碼(XSS)的漏洞報告。一般來說,我們不認為這些情況是真正的漏洞,因為沒有實際的方法可以保護開發者免受允許 XSS 的兩種場景。
開發者明確要求 Vue 將使用者提供的未經過濾的內容作為 Vue 模板進行渲染。這是固有的不安全行為,Vue 無法知道其來源。
開發者將 Vue 安裝在一個包含伺服器端渲染和使用者提供內容的整個 HTML 頁面上。這與 #1 基本上是同一個問題,但有時開發者可能沒有意識到這一點。這可能導致攻擊者提供作為純 HTML 安全但作為 Vue 模板不安全的 HTML。最佳實踐是 永遠不要在可能包含伺服器端渲染和使用者提供內容的節點上安裝 Vue。
最佳實踐
一般規則是,如果您允許未經過濾的使用者提供的內容被執行(無論是作為 HTML、JavaScript 還是 CSS),您可能使自己容易受到攻擊。無論使用 Vue、其他框架,還是根本不使用框架,這些建議實際上都是正確的。
除了上述 潛在危險 的建議外,我們還建議您熟悉這些資源
然後使用您學到的知識來審查您的依賴項的原始碼,以尋找潛在的危險模式,如果其中任何包含第三方元件或以其他方式影響渲染到 DOM 的內容。
後端協調
HTTP安全漏洞,如跨站請求偽造(CSRF/XSRF)和跨站指令碼包含(XSSI),主要在後端解決,因此它們不是Vue的關注點。然而,與您的後端團隊溝通以瞭解如何最好地與他們互動仍然是一個好主意,例如,透過在表單提交中提交CSRF令牌。
伺服器端渲染(SSR)
使用SSR時,還有一些額外的安全關注點,因此請確保遵循我們在我們的SSR文件中概述的最佳實踐,以避免漏洞。