《前端之路》 之 前端 安全 XSS 原理以及防御手段


什么是 XSS

一、XSS

什么是 XSS

XSS,即 Cross Site Script , 翻譯過來就是 跨站腳本攻擊;為了和 css 有所區分,因而在安全領域被稱為 XSS。

什么是 XSS 攻擊

XSS 攻擊指的是 攻擊者在網站上注入惡意的客戶端代碼,通過惡意腳本對客戶端網頁進行篡改,從而在別的用戶瀏覽網頁的 時候,對用戶進行控制或者獲取 用戶對隱私數據的 這么一種攻擊手段。

XSS 攻擊的方式 是什么

XSS 攻擊可以分為3類:反射型(非持久型)、存儲型(持久型)、基於DOM。

XSS攻擊需要具備兩個條件:需要向web頁面注入惡意代碼;這些惡意代碼能夠被瀏覽器成功的執行。

用戶注入的 惡意腳本一般包括 JavaScript 、HTML、Flash。很多種的 XSS 攻擊方式,但是共同點是: 將一些 隱私數據像:1、cookie、session 發送給攻擊者。 2、將受害者重定向到一個由攻擊者控制的網站(俗稱釣魚網站),在受害者的機器上進行一些惡意操作。

反射型(非持久型)的 XSS 攻擊

XSS反射型攻擊,惡意代碼並沒有保存在目標網站,而是通過引誘用戶點擊一個鏈接到目標網站的惡意鏈接來實施攻擊的。

直接這么解釋還是有點難懂的。下面,我們還是來看個 demo

<a href="http://127.0.0.1:1212/login/<img src=''  onerror='alert(document.cookie)'>" target="_blank" >這是 XSS 的惡意鏈接</a>

假設某用戶在黑客點釣魚網站上 點擊了這個 帶有 XSS 攻擊的惡意鏈接。就會跳轉到 http://127.0.0.1:1212 這個網站上。剛好這個路徑下的 鏈接是會有一個 發生一個 get 請求。
那么這個時候 <img src='' onerror='alert(document.cookie)'> 這部分的內容就被 當作 請求的 內容發送給了 服務端。如果服務端 為對該 內容進行 XSS 防御,直接返回給 瀏覽器。

那么這個時候就會出現 XSS 攻擊了。<img src='' onerror='alert(document.cookie)'> 這句代碼被顯示在了 瀏覽器上,因為 img 標簽也具有 跨域屬性,直接執行了 onerror 中的 JS 代碼。 黑客這個時候就可以 在目標網站上 為所欲為了。

比如這里就是 簡單的 alert 了 所有的 cookie。但是,如果我是黑客的話,我肯定會把 用戶的 cookie、localStorage、等等重要信息 全部上傳到我的服務器,然后進行拿到各類想要的信息。從而獲益。

存儲型(持久型)的 XSS 攻擊

存儲型(持久型)的 XSS 攻擊 和 反射型 其實也有異曲同工之妙呀。

這么多,我哪里記得住?

別慌,我們慢慢分析一波就都能記住啦~

惡意代碼 通過表單提交的方式 被保存到目標網站的服務器中,這種攻擊具有較強的穩定性和持久性,比較常見場景是在博客,論壇、OA、CRM等社交網站上,比如:某CRM系統的客戶投訴功能上存在XSS存儲型漏洞,黑客提交了惡意攻擊代碼,當系統管理員查看投訴信息時惡意代碼執行,竊取了客戶的資料,然而管理員毫不知情,這就是典型的XSS存儲型攻擊。

我們還是寫個 demo 來方便 理解吧

    <div><textarea id="textarea" class="text"></textarea></div>
    <button id="btn" class="botton">submit</button>

大概就長這個樣子了:

textarea 內則為 帶有 xss 的代碼,點擊提交。直接 xhr 請求到 node 的服務端。

node 服務端 接收到 傳入的參數 不做任何 xss 防御 直接保存起來的 js demo
一般是存儲 sql 但是這里方便起見 我們就直接存 memory-cache ,代碼如下:

router.post("/upload", (ctx, next) => {
  let curData = JSON.stringify(ctx.request.body);
  cache.put("xss", curData);
  ctx.body = `<div>${curData}</div>`;
});

我們請求 一個新的路徑來將 memory-cache 的值獲取到。 node 端 代碼:

router.get("/getName", (ctx, next) => {
  let curData = cache.get("xss");
  ctx.body = `<div>${JSON.parse(curData)}</div>`;
});

接下來就是訪問 http://127.0.0.1:1212/getName

得到 如下 畫面:

當然,黑客不會 alert 你的 cookie 信息。 直接 post 到 一個第三方的 服務器上,然后直接模擬瀏覽器訪問,那就簡直了。

基於 DOM 的 XSS 攻擊

基於 DOM 的 XSS 攻擊是指通過惡意腳本修改頁面的 DOM 結構,是純粹發生在客戶端的攻擊。

    const divXss = document.getElementById("xss");
    const xssbtn = document.getElementById("xssbtn");

    const val = `'' onclick=alert(/xss/)`;

    xssbtn.addEventListener("click", function() {
      divXss.innerHTML = `<a href=${val}>testLink</a>`;
    });

當然上面的這個 val 往往是黑客 通過 input 或者 textarea 的 form表單提交引起的

當用戶下意識的去點擊 這個新增的 dom 的時候,就會出現 如下 場景:

黑客又可以為所欲為了。

二、XSS 的 防御

HttpOnly 最早由微軟提出,至今已經成為一個標准。瀏覽器將禁止頁面的Javascript 通過 document.cookie 獲取帶有 HttpOnly 屬性的Cookie。

上文有說到,攻擊者可以通過注入惡意腳本獲取用戶的 Cookie 信息。通常 Cookie 中都包含了用戶的登錄憑證信息,攻擊者在獲取到 Cookie 之后,則可以發起 Cookie 劫持攻擊。所以,嚴格來說,HttpOnly 並非阻止 XSS 攻擊,而是能阻止 XSS 攻擊后的 Cookie 劫持攻擊。

輸入檢查

不要相信用戶的任何輸入。 對於用戶的任何輸入要進行檢查、過濾和轉義。建立可信任的字符和 HTML 標簽白名單,對於不在白名單之列的字符或者標簽進行過濾或編碼。

在 XSS 防御中,輸入檢查一般是檢查用戶輸入的數據中是否包含 <,> 等特殊字符,如果存在,則對特殊字符進行過濾或編碼,這種方式也稱為 XSS Filter。

而在一些前端框架中,都會有一份 decodingMap, 用於對用戶輸入所包含的特殊字符或標簽進行編碼或過濾,如 <,>,script,防止 XSS 攻擊:

// vuejs 中的 decodingMap
// 在 vuejs 中,如果輸入帶 script 標簽的內容,會直接過濾掉
const decodingMap = {
'<': '<',
'>': '>',
'"': '"',
'&': '&',
' ': '\n'
}

輸出檢查

用戶的輸入會存在問題,服務端的輸出也會存在問題。一般來說,除富文本的輸出外,在變量輸出到 HTML 頁面時,可以使用編碼或轉義的方式來防御 XSS 攻擊。

例如利用 sanitize-html 對輸出內容進行有規則的過濾之后再輸出到頁面中。

本 demo 中的 koa 框架其實在輸出的時候處理了標簽:

這個時候 就會 減少 99% 的 xss 攻擊了。是不是發現選擇一款好的框架能節省好多的麻煩。

好了,這篇關於 XSS 的文章就介紹到 這里了,別着急 源碼會放出來的。

全文的 demo 的源碼地址: github源碼地址

總結

一旦在DOM解析過程成出現不在預期內的改變,就有可能發生 XSS。
失控 就會出現 BUG。
防御手段 既然 攻防的人都知道了,那么自身代碼的嚴謹程度就決定了整個項目的安度。
突然想起了 PDD ...

GitHub 地址:(歡迎 star 、歡迎推薦 : )

前端 安全 XSS 原理以及防御手段


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM