前端安全之XSS攻擊

来源:http://www.cnblogs.com/unclekeith/archive/2017/10/29/7750681.html
-Advertisement-
Play Games

前端安全之XSS 轉載請註明出處:unclekeith: "前端安全之XSS" XSS定義 XSS, 即為(Cross Site Scripting), 中文名為跨站腳本, 是發生在 目標用戶的瀏覽器 層面上的,當渲染DOM樹的過程成發生了 不在預期內 執行的JS代碼時,就發生了XSS攻擊。 跨站腳 ...


前端安全之XSS

轉載請註明出處:unclekeith: 前端安全之XSS

XSS定義

XSS, 即為(Cross Site Scripting), 中文名為跨站腳本, 是發生在目標用戶的瀏覽器層面上的,當渲染DOM樹的過程成發生了不在預期內執行的JS代碼時,就發生了XSS攻擊。

跨站腳本的重點不在‘跨站’上,而在於‘腳本’上。大多數XSS攻擊的主要方式是嵌入一段遠程或者第三方域上的JS代碼。實際上是在目標網站的作用域下執行了這段js代碼。

XSS攻擊方式

反射型 XSS

反射型XSS,也叫非持久型XSS,是指發生請求時,XSS代碼出現在請求URL中,作為參數提交到伺服器,伺服器解析並響應。響應結果中包含XSS代碼,最後瀏覽器解析並執行。

從概念上可以看出,反射型XSS代碼是首先出現在URL中的,然後需要服務端解析,最後需要瀏覽器解析之後XSS代碼才能夠攻擊。

舉一個小慄子。

使用express起一個web伺服器,然後設置一下請求介面。通過ajax的GET請求將參數發往伺服器,伺服器解析成json後響應。將返回的數據解析後顯示到頁面上。(沒有對返回的數據進行解碼和過濾等操作。)

html
<textarea name="txt" id="txt" cols="80" rows="10">
<button type="button" id="test">測試</button>

js
var test = document.querySelector('#test')
test.addEventListener('click', function () {
  var url = `/test?test=${txt.value}`   // 1. 發送一個GET請求
  var xhr = new XMLHttpRequest()
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
        // 3. 客戶端解析JSON,並執行
        var str = JSON.parse(xhr.responseText).test
        var node = `${str}`
        document.body.insertAdjacentHTML('beforeend', node)
      } else {
        console.log('error', xhr.responseText)
      }
    }
  }
  xhr.open('GET', url, true)
  xhr.send(null)
}, false)

express
var express = require('express');
var router = express.Router();

router.get('/test', function (req, res, next) {
 // 2. 服務端解析成JSON後響應
  res.json({
    test: req.query.test
  })
})

現在我們通過給textarea添加一段有攻擊目的的img標簽,

<img src="null" onerror='alert(document.cookie)' />

實際的頁面時這樣的。

ok現在,我們點擊<測試>按鈕,一個XSS攻擊就發生了。下麵圖片中是獲取了本地的部分cookie信息

實際上,我們只是模擬攻擊,通過alert獲取到了個人的cookie信息。但是如果是黑客的話,他們會註入一段第三方的js代碼,然後將獲取到的cookie信息存到他們的伺服器上。這樣的話黑客們就有機會拿到我們的身份認證做一些違法的事情了。

以上,存在的一些問題,主要在於沒有對用戶輸入的信息進行過濾,同時沒有剔除掉DOM節點中存在的一些有危害的事件和一些有危害的DOM節點。

存儲型 XSS
存儲型XSS,也叫持久型XSS,主要是將XSS代碼發送到伺服器(不管是資料庫、記憶體還是文件系統等。),然後在下次請求頁面的時候就不用帶上XSS代碼了。

最典型的就是留言板XSS。用戶提交了一條包含XSS代碼的留言到資料庫。當目標用戶查詢留言時,那些留言的內容會從伺服器解析之後載入出來。瀏覽器發現有XSS代碼,就當做正常的HTML和JS解析執行。XSS攻擊就發生了。
DOM XSS
DOM XSS攻擊不同於反射型XSS和存儲型XSS,DOM XSS代碼不需要伺服器端的解析響應的直接參与,而是通過瀏覽器端的DOM解析。這完全是客戶端的事情。

DOM XSS代碼的攻擊發生的可能在於我們編寫JS代碼造成的。我們知道eval語句有一個作用是將一段字元串轉換為真正的JS語句,因此在JS中使用eval是很危險的事情,容易造成XSS攻擊。避免使用eval語句。

如以下代碼

test.addEventListener('click', function () {
  var node = window.eval(txt.value)
  window.alert(node)
}, false)

txt中的代碼如下
<img src='null' onerror='alert(123)' />

以上通過eval語句就造成了XSS攻擊。

XSS危害

  1. 通過document.cookie盜取cookie
  2. 使用js或css破壞頁面正常的結構與樣式
  3. 流量劫持(通過訪問某段具有window.location.href定位到其他頁面)
  4. Dos攻擊:利用合理的客戶端請求來占用過多的伺服器資源,從而使合法用戶無法得到伺服器響應。

XSS防禦

從以上的反射型和DOM XSS攻擊可以看出,我們不能原樣的將用戶輸入的數據直接存到伺服器,需要對數據進行一些處理。以上的代碼出現的一些問題如下

  1. 沒有過濾危險的DOM節點。如具有執行腳本能力的script, 具有顯示廣告和色情圖片的img, 具有改變樣式的link, style, 具有內嵌頁面的iframe, frame等元素節點。
  2. 沒有過濾危險的屬性節點。如事件, style, src, href等
  3. 沒有對cookie設置httpOnly。

如果將以上三點都在渲染過程中過濾,那麼出現的XSS攻擊的概率也就小很多。

解決方法如下

對cookie的保護

  1. 對重要的cookie設置httpOnly, 防止客戶端通過document.cookie讀取cookie。服務端可以設置此欄位。

對用戶輸入數據的處理

  1. 編碼:不能對用戶輸入的內容都保持原樣,對用戶輸入的數據進行字元實體編碼。對於字元實體的概念可以參考文章底部給出的參考鏈接。
  2. 解碼:原樣顯示內容的時候必須解碼,不然顯示不到內容了。
  3. 過濾:把輸入的一些不合法的東西都過濾掉,從而保證安全性。如移除用戶上傳的DOM屬性,如onerror,移除用戶上傳的Style節點,iframe, script節點等。

通過一個例子講解一下如何處理用戶輸入的數據。

實現原理如下:

  1. 存在一個parse函數,對輸入的數據進行處理,返回處理之後的數據
  2. 對輸入的數據(如DOM節點)進行解碼(使用第三方庫 he.js)
  3. 過濾掉一些元素有危害的元素節點與屬性節點。如script標簽,onerror事件等。(使用第三方庫HTMLParser.js)
<script src='/javascripts/htmlparse.js'></script>
<script src='/javascripts/he.js'></script>
// 第三方庫資源在文章底部給出

// parse函數實現如下

function parse (str) {
      // str假如為某個DOM字元串
      // 1. result為處理之後的DOM節點
      let result = ''
      // 2. 解碼
      let decode = he.unescape(str, {
          strict: true
      })
      HTMLParser(decode, {
          start (tag, attrs, unary) {
              // 3. 過濾常見危險的標簽
              if (tag === 'script' || tag === 'img' || tag === 'link' || tag === 'style' || tag === 'iframe' || tag === 'frame') return
              result += `<${tag}`
              for (let i = 0; i < attrs.length; i++) {
                  let name = (attrs[i].name).toLowerCase()
                  let value = attrs[i].escaped
                  // 3. 過濾掉危險的style屬性和js事件
                  if (name === 'style' || name === 'href' || name === 'src' || ~name.indexOf('on')) continue
                  result += ` ${name}=${value}`
              }
              result += `${unary ? ' /' : ''} >`
          },
          chars (text) {
              result += text
          },
          comment (text) {
              result += `<!-- ${text} -->`
          },
          end (tag) {
              result += `</${tag}>`
          }
      })
      return result
  }

因此,有了以上的parse函數之後,就可以避免大部分的xss攻擊了。

test.addEventListener('click', function () {
  // ... 省略部分代碼
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
        // 3. 客戶端解析JSON,並執行
        // test按鈕的點擊事件中唯一的變化就是使用parse對服務端返回的數據進行瞭解碼和過濾的處理。
        var str = parse(JSON.parse(xhr.responseText).test)
        // 通過parse解析之後返回的數據就是安全的DOM字元串
        var node = `${str}`
        document.body.insertAdjacentHTML('beforeend', node)
      }
    }
  }
  // ... 省略部分代碼
}, false)

那麼,慄子說完了。

稍微總結一下

  1. 一旦在DOM解析過程成出現不在預期內的改變(JS代碼執行或樣式大量變化時),就可能發生XSS攻擊
  2. XSS分為反射型XSS,存儲型XSS和DOM XSS
  3. 反射型XSS是在將XSS代碼放在URL中,將參數提交到伺服器。伺服器解析後響應,在響應結果中存在XSS代碼,最終通過瀏覽器解析執行。
  4. 存儲型XSS是將XSS代碼存儲到服務端(資料庫、記憶體、文件系統等),在下次請求同一個頁面時就不需要帶上XSS代碼了,而是從伺服器讀取。
  5. DOM XSS的發生主要是在JS中使用eval造成的,所以應當避免使用eval語句。
  6. XSS危害有盜取用戶cookie,通過JS或CSS改變樣式,DDos造成正常用戶無法得到伺服器響應。
  7. XSS代碼的預防主要通過對數據解碼,再過濾掉危險標簽、屬性和事件等。

參考資源

  1. 《WEB前端黑客技術揭秘》
  2. 淺談XSS攻擊的那些事(附常用繞過姿勢)
  3. XSS實戰:我是如何拿下你的百度賬號
  4. HTMLParser
  5. he
  6. Web安全-XSS

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 通過 2. 通過非同步請求 3. 通過jQuery ...
  • 備註:第一次翻譯技術文章,標題都糾結了好久不知道腫麽翻譯,如發現翻譯不當之處,可點擊github鏈接提交評論,thx~ 前幾天我為一個項目寫README文檔,我希望其他開發者能夠看到這個項目,並從中學到一些東西。突然我意識到,若放在幾年前,我寫作的過程中隨口提到的Node,npm,Homebrew, ...
  • 一.介紹 本篇是續上一篇的,引用類型的後篇,本篇主要是說基本包裝類型和個體內置對象。如果你能收穫一些知識,那我很高興,很滿足,哈哈哈,希望大家能愉快看完。如果你想學好一門技術,要不忘初心,方得始終。 二.基本包裝類型 先說明基本包裝類型也是屬於引用類型,是接著上一篇的,強調一下. 然後我們記住兩句話 ...
  • ## 寫在前面 因為對Vue.js很感興趣,而且平時工作的技術棧也是Vue.js,這幾個月花了些時間研究學習了一下Vue.js源碼,並做了總結與輸出。 文章的原地址:[https://github.com/answershuto/learnVue](https://github.com/answer ...
  • 一、交換兩個數字的值 我們交換兩個數字的值想到的方法一般就是用一個新的變變數,讓他把一個數存起來,然後在交換兩個數字的值,看下麵這種。 看下麵這段代碼,也可以交換兩個數字的值,如果這樣寫你會不會發現特別高大上。 二、數組的排序 1.數組方法中的sort排序方法。 這是數組方法中的sort排序方法,如 ...
  • 想成為一個高效的Web開發者嗎?來看看大牛分享的經驗吧~ 作為一個軟(ku)件(bi)工(de)程(ma)師(nong),你有沒有覺得做什麼事都沒時間?沒時間學習新東西,沒時間去回顧、整理原來寫的爛代碼,沒時間寫單元測試,沒時間給接管你項目的家伙寫文檔,沒時間思考,沒時間喘氣,沒!時!間! 額……如 ...
  • 這篇文章介紹十款讓 Web 前端開發人員生活更輕鬆的實用工具。每個Web開發人員都有自己的工具箱,這樣工作中碰到的每個問題都有一個好的解決方案供選擇。 對於每一項工作,開發人員需要特定的輔助工具,所以如果下麵這些工具對於你來說都是新的領域,那麼這篇文章是非常有用的,因為這些實用的工具將讓你的工作更有 ...
  • Layer layer是一款近年來備受青睞的web彈層組件,她具備全方位的解決方案,致力於服務各水平段的開發人員,您的頁面會輕鬆地擁有豐富友好的操作體驗。 在與同類組件的比較中,layer總是能輕易獲勝。她儘可能地在以更少的代碼展現更強健的功能,且格外註重性能的提升、易用和實用性! 如果,你初識la ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...