Web 安全漏洞之 XSS 攻擊

編者說:做爲JS系工程師接觸最多的漏洞我想就是 XSS 漏洞了,然鵝並非全部的同窗對其都有一個清晰的認識。今天咱們請來了@盧士傑 同窗爲咱們分享他眼中的 XSS 漏洞攻擊,但願能幫助到你們。css


什麼是 XSS 攻擊

XSS(Cross-Site Scripting)又稱跨站腳本,XSS的重點不在於跨站點,而是在於腳本的執行。XSS是一種常常出如今 Web 應用程序中的計算機安全漏洞,是因爲 Web 應用程序對用戶的輸入過濾不足而產生的。前端

常見的 XSS 攻擊有三種:反射型、DOM-based 型、存儲型。 其中反射型、DOM-based 型能夠歸類爲非持久型 XSS 攻擊,存儲型歸類爲持久型 XSS 攻擊。jquery

1.反射型

反射型 XSS 通常是攻擊者經過特定手法(如電子郵件),誘使用戶去訪問一個包含惡意代碼的 URL,當受害者點擊這些專門設計的連接的時候,惡意代碼會直接在受害者主機上的瀏覽器執行。git

對於訪問者而言是一次性的,具體表如今咱們把咱們的惡意腳本經過 URL 的方式傳遞給了服務器,而服務器則只是不加處理的把腳本「反射」回訪問者的瀏覽器而使訪問者的瀏覽器執行相應的腳本。反射型 XSS 的觸發有後端的參與,要避免反射性 XSS,必須須要後端的協調,後端解析前端的數據時首先作相關的字串檢測和轉義處理。github

此類 XSS 一般出如今網站的搜索欄、用戶登陸口等地方,經常使用來竊取客戶端 Cookies 或進行釣魚欺騙。數據庫

整個攻擊過程大約以下:後端

反射型

2.DOM-based 型

客戶端的腳本程序能夠動態地檢查和修改頁面內容,而不依賴於服務器端的數據。例如客戶端如從 URL 中提取數據並在本地執行,若是用戶在客戶端輸入的數據包含了惡意的 JavaScript 腳本,而這些腳本沒有通過適當的過濾和消毒,那麼應用程序就可能受到 DOM-based XSS 攻擊。須要特別注意如下的用戶輸入源 document.URLlocation.hashlocation.searchdocument.referrer 等。瀏覽器

整個攻擊過程大約以下:安全

DOM-based

3.存儲型

攻擊者事先將惡意代碼上傳或儲存到漏洞服務器中,只要受害者瀏覽包含此惡意代碼的頁面就會執行惡意代碼。這就意味着只要訪問了這個頁面的訪客,都有可能會執行這段惡意腳本,所以儲存型XSS的危害會更大。服務器

存儲型 XSS 通常出如今網站留言、評論、博客日誌等交互處,惡意腳本存儲到客戶端或者服務端的數據庫中。

整個攻擊過程大約以下:

DOM-based

XSS 攻擊的危害

XSS 能夠致使:

  1. 攻擊劫持訪問;
  2. 盜用 cookie 實現無密碼登陸;
  3. 配合 csrf 攻擊完成惡意請求;
  4. 使用 js 或 css 破壞頁面正常的結構與樣式等;

防護方法

1. XSS 防護之 HTML 編碼

應用範圍:將不可信數據放入到 HTML 標籤內(例如div、span等)的時候進行HTML編碼。

編碼規則:將 & < > " ' / 轉義爲實體字符(或者十進制、十六進制)。

示例代碼:

function encodeForHTML(str, kwargs){
    return ('' + str)
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')     // DEC=> &#60; HEX=> &#x3c; Entity=> &lt;
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#x27;')   // &apos; 不推薦,由於它不在HTML規範中
      .replace(/\//g, '&#x2F;');
  };
複製代碼

HTML 有三種編碼表現方式:十進制、十六進制、命名實體。例如小於號(<)能夠編碼爲 "十進制> <", "十六進制=> <", "命名實體=> <" 三種方式。對於單引號(')因爲實體字符編碼方式不在 HTML 規範中,因此此處使用了十六進制編碼。

2. XSS 防護之 HTML Attribute 編碼

應用範圍:將不可信數據放入 HTML 屬性時(不含src、href、style 和事件處理屬性),進行 HTML Attribute 編碼

編碼規則:除了字母數字字符之外,使用 &#xHH;(或者可用的命名實體)格式來轉義ASCII值小於256全部的字符​​​​​​​

示例代碼:

function encodeForHTMLAttibute(str, kwargs){
    let encoded = '';
    for(let i = 0; i < str.length; i++) {
      let ch = hex = str[i];
      if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
        hex = '&#x' + ch.charCodeAt(0).toString(16) + ';';
      }
      encoded += hex;
    }
    return encoded;
  };
複製代碼

3. XSS 防護之 JavaScript 編碼

做用範圍:將不可信數據放入事件處理屬性、JavaScirpt值時進行 JavaScript 編碼

編碼規則:除字母數字字符外,請使用\xHH格式轉義ASCII碼小於256的全部字符

示例代碼:

function encodeForJavascript(str, kwargs) {
    let encoded = '';
    for(let i = 0; i < str.length; i++) {
      let cc = hex = str[i];
      if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
        hex = '\\x' + cc.charCodeAt().toString(16);
      }
      encoded += hex;
    }
    return encoded;
  };
複製代碼

4. XSS 防護之 URL 編碼

做用範圍:將不可信數據做爲 URL 參數值時須要對參數進行 URL 編碼

編碼規則:將參數值進行 encodeURIComponent 編碼

示例代碼:

function encodeForURL(str, kwargs){
    return encodeURIComponent(str);
  };
複製代碼

5. XSS 防護之 CSS 編碼

做用範圍:將不可信數據做爲 CSS 時進行 CSS 編碼

編碼規則:除了字母數字字符之外,使用\XXXXXX格式來轉義ASCII值小於256的全部字符

示例代碼:

function encodeForCSS (attr, str, kwargs){
    let encoded = '';
    for (let i = 0; i < str.length; i++) {
      let ch = str.charAt(i);
      if (!ch.match(/[a-zA-Z0-9]/) {
        let hex = str.charCodeAt(i).toString(16);
        let pad = '000000'.substr((hex.length));
        encoded += '\\' + pad + hex;
      } else {
        encoded += ch;
      }
    }
    return encoded;
  };
複製代碼

後記

在任什麼時候候用戶的輸入都是不可信的。對於 HTTP 參數,理論上都要進行驗證,例如某個字段是枚舉類型,其就不該該出現枚舉覺得的值;對於不可信數據的輸出要進行相應的編碼;此外httpOnlyCSPX-XSS-ProtectionSecure Cookie 等也能夠起到有效的防禦。

XSS 漏洞有時比較難發現,所幸當下React、Vue等框架都從框架層面引入了 XSS 防護機制,必定程度上解放了咱們的雙手。 可是做爲開發人員依然要了解 XSS 基本知識、於細節處避免製造 XSS 漏洞。框架是輔助,咱們仍需以人爲本,規範開發習慣,提升 Web 前端安全意識。

參考文檔

相關文章
相關標籤/搜索