XSS攻擊,這次一定會!

語言: CN / TW / HK

theme: orange

完整閱讀本文大約需要5分鐘。

開啟本文前,先提出兩個我在面試時被問到的題:

  1. 為了預防XSS攻擊,我們會對使用者的輸入內容進行過濾,轉義的時機應該是a.輸入時前端處理 b.落庫時後端處理 c.拼接HTML時 ?
  2. XSS攻擊的預防,需要前端還是後端去做?

什麼是XSS攻擊

XSS攻擊是Cross-Site Scripting的縮寫,直白來說,就是頁面被注入了惡意的程式碼——使用者輸入的內容跳出文字的限制,成了可執行的程式碼。

XSS攻擊的分類

根據入侵程式碼的來源,通常將XSS攻擊分成三類:

儲存型 XSS 攻擊

特點:惡意程式碼已經落庫,被拼接到HTML中返回。

  1. 攻擊者通過論壇評論區提交惡意程式碼到資料庫;
  2. 其他使用者開啟論壇,服務端把惡意程式碼取出來,拼接在HTML中返回;
  3. 惡意程式碼在使用者的瀏覽器端執行;

除了論壇,這類攻擊還常見於使用者私信傳送。

比如使用者提交評論<script>alert('XSS');</script>到網站的資料庫中。

```

  評論內容:<%= getContent("comment") %>

```

被後端拼接後:

```

  評論內容:

```

其他使用者訪問到這個頁面,會跳出寫著”XSS”的對話方塊

反射型 XSS 攻擊

特點:惡意程式碼被拼接到URL上,被拼接到HTML中返回。

  1. 攻擊者拼接出包含惡意程式碼的受害網站URL,誘導使用者點選;
  2. 使用者點選該URL,目標網站的伺服器取出惡意程式碼,拼接到HTML返回;
  3. 惡意程式碼在其他使用者的瀏覽器端執行;

這類攻擊需要使用者主動點選受害網站的URL,攻擊者會通過通過QQ群或者郵件等方式誘導點選。

比如一個惡意URL可以長這樣:http://xxx/search?keyword="<script>alert('XSS');</script>

```

  你好<%= getParameter("keyword") %>

```

被後端拼接後:

```

  你好

```

點選後,頁面會跳出寫著”XSS”的對話方塊。

DOM 型 XSS 攻擊

特點:惡意程式碼被拼接到URL上,被前端JavaScript程式碼執行。

  1. 攻擊者拼接出包含惡意程式碼的受害網站URL,誘導使用者點選;
  2. 使用者點選該URL;
  3. 前端 JavaScript 取出 URL 中的惡意程式碼,惡意程式碼在使用者的瀏覽器端執行;

DOM型和反射型的區別在於,DOM 型 XSS 攻擊中,取出和執行惡意程式碼由瀏覽器端完成,屬於前端 JavaScript 自身的安全漏洞。而其他兩種 XSS 都屬於服務端的安全漏洞。

上述三種XSS攻擊的目的都一致:惡意程式碼在瀏覽器端執行後,竊取使用者的本地儲存資料:通過document.cookie獲取使用者的身份憑證,然後通過網路請求將資料傳送給惡意伺服器

接下來就可以進行下一步:冒充使用者去對受害網站發起請求完成指定操作,比如轉賬給攻擊者的賬戶。

怎麼預防XSS攻擊

XSS攻擊的實現需要有兩個必要條件:

  1. 攻擊者輸入惡意程式碼;
  2. 瀏覽器執行惡意程式碼;

先看第一點,是否可以避免攻擊者輸入惡意程式碼,先進行HTML轉義呢?

如果我們在前端對輸入的內容進行轉義過濾,那麼攻擊者只要模擬發起請求,便繞了過前端,一樣可以攻擊成功。

如果落庫時在後端進行轉義過濾,我們會發現:

  1. 如果內容要提供給多端,只會在前端正常展示,在iOS/安卓上會變成亂碼;

  2. 返回給前端的方式不一樣,也不一定能正常展示,比如,正常的使用者輸入了 5 < 7 這個內容,在寫入資料庫前,被轉義,變成了 5 &lt; 7;

    1. 作為 HTML 拼接頁面時,可以正常顯示;
    2. 通過 Ajax 返回,然後賦值給 JavaScript 的變數時,前端得到的字串就是轉義後的字元。這個內容不能直接用於 Vue 等模板的展示,會和iOS/安卓一樣,變成亂碼 5 &lt; 7

所以我們需要通過“防止瀏覽器執行惡意程式碼”來防範 XSS 攻擊。

純前端渲染

純前端渲染是指,瀏覽器首先載入一個空白的HTML,然後執行該HTML引入的JS檔案,JS通過AJAX獲取業務資料,呼叫DOM API,更新到頁面上。

因為是在前端,我們可以清楚地告訴瀏覽器:這是文字.innerText而不是HTML.innerHTML。這樣瀏覽器就不會執行預期意外的程式碼。

純前端渲染可以避免儲存型和反射型的攻擊,但沒法避免DOM型,攻擊者可以通過onload事件、href中嵌入javascript:...進行攻擊。

轉義HTML

對於需要考慮SEO的SSR專案,不得不在服務端拼接HTML檔案。那麼必須使用HTML轉義庫,基本規則是將& < > " ' /幾個字元轉義掉。

關注高危API

在前端渲染時,要謹慎使用.innerHTML.outerHTMLdocument.write()等直接插入HTML的API,其來源必須是可信的。

此外locationonclickonerroronloadonmouseover、還有 <a> 標籤的 href 都可以把字串當作程式碼執行。

其他通用策略

  1. 使用CSP:CSP即Content Security Policy內容安全策略,限制載入其他域下的資源,這樣即使黑客插入了一個 Javascript檔案,它也是無法被載入的;
  2. 開啟HTTP only:禁止 JavaScript 讀取某些敏感 Cookie,攻擊者完成 XSS 注入後也無法竊取此 Cookie;
  3. 驗證碼:防止指令碼冒充使用者提交危險操作;

結語

讀完本文,回到開頭兩個問題,我們知道了:

  1. 對使用者輸入內容轉義,其時機必須在拼接HTML時,如果在落庫前處理,會導致iOS/安卓亂碼;
  2. XSS攻擊的預防,需要RD一起完成,儲存型和反射型攻擊是後端的責任,DOM型是前端的責任;

IMG_6474.JPG