WEB安全

WEB安全

XSS 攻擊

什麼是XSS攻擊?

Cross-Site Scripting(跨站腳本攻擊)簡稱 XSS,是一種代碼注入攻擊。攻擊者經過在目標網站上注入惡意腳本,使之在用戶的瀏覽器上運行。利用這些惡意腳本,攻擊者可獲取用戶的敏感信息如 Cookie、SessionID 等,進而危害數據安全。php

爲了區分CSS,改成XSS。html

XSS 的本質是:惡意代碼未通過濾,與網站正常的代碼混在一塊兒;瀏覽器沒法分辨哪些腳本是可信的,致使惡意腳本被執行。前端

XSS分類

根據攻擊的來源,XSS 攻擊可分爲存儲型、反射型和 DOM 型三種。數據庫

類型 存儲區 插入點
存儲型 XSS 後端數據庫 HTML
反射型 XSS URL HTML
DOM 型 XSS 後端數據庫/前端存儲/URL 前端 JavaScript

存儲區:惡意代碼存放的位置。後端

插入點:由誰取得惡意代碼,並插入到網頁上。瀏覽器

存儲型XSS

這種攻擊常見於帶有用戶保存數據的網站功能,如論壇發帖、商品評論、用戶私信等。安全

反射型XSS

反射型 XSS 跟存儲型 XSS 的區別是:存儲型 XSS 的惡意代碼存在數據庫裏,反射型 XSS 的惡意代碼存在 URL 裏。bash

反射型 XSS 漏洞常見於經過 URL 傳遞參數的功能,如網站搜索、跳轉等。服務器

因爲須要用戶主動打開惡意的 URL 才能生效,攻擊者每每會結合多種手段誘導用戶點擊。cookie

POST 的內容也能夠觸發反射型 XSS,只不過其觸發條件比較苛刻(須要構造表單提交頁面,並引導用戶點擊),因此很是少見。

DOM型XSS

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

XSS預防

  • 攻擊者提交惡意代碼
  • 瀏覽器執行惡意代碼

攻擊者提交惡意代碼

輸入側過濾可以在某些狀況下解決特定的 XSS 問題,但會引入很大的不肯定性和亂碼問題。在防範 XSS 攻擊時應避免此類方法。

瀏覽器執行惡意代碼

  • 防止 HTML 中出現注入
  • 防止 JavaScript 執行時,執行惡意代碼

預防存儲型和反射型 XSS 攻擊

存儲型和反射型 XSS 都是在服務端取出惡意代碼後,插入到響應 HTML 裏的,攻擊者刻意編寫的「數據」被內嵌到「代碼」中,被瀏覽器所執行。

預防這兩種漏洞,有兩種常見作法:

1.改爲純前端渲染,把代碼和數據分隔開。

2.對 HTML 作充分轉義。

純前端渲染

1.瀏覽器先加載一個靜態 HTML,此 HTML 中不包含任何跟業務相關的數據。

2.而後瀏覽器執行 HTML 中的 JavaScript。

3.JavaScript 經過 Ajax 加載業務數據,調用 DOM API 更新到頁面上。

在純前端渲染中,咱們會明確的告訴瀏覽器:下面要設置的內容是文本(.innerText),仍是屬性(.setAttribute),仍是樣式(.style)等等。瀏覽器不會被輕易的被欺騙,執行預期外的代碼了。

轉義HTML

若是拼接 HTML 是必要的,就須要採用合適的轉義庫,對 HTML 模板各處插入點進行充分的轉義。

經常使用的模板引擎,如 doT.js、ejs、FreeMarker 等,對於 HTML 轉義一般只有一個規則,就是把 & < > " ' / 這幾個字符轉義掉,確實能起到必定的 XSS 防禦做用,但並不完善:

XSS 安全漏洞 簡單轉義是否有防禦做用
HTML 標籤文字內容
HTML 屬性值
CSS 內聯樣式
內聯 JavaScript
內聯 JSON
跳轉連接

預防 DOM 型 XSS 攻擊

DOM 型 XSS 攻擊,實際上就是網站前端 JavaScript 代碼自己不夠嚴謹,把不可信的數據看成代碼執行了。

在使用 .innerHTML、.outerHTML、document.write() 時要特別當心,不要把不可信的數據做爲 HTML 插到頁面上,而應儘可能使用 .textContent、.setAttribute() 等。

若是用 Vue/React 技術棧,而且不使用 v-html/dangerouslySetInnerHTML 功能,就在前端 render 階段避免 innerHTML、outerHTML 的 XSS 隱患。

DOM 中的內聯事件監聽器,如 location、onclick、onerror、onload、onmouseover 等, 標籤的 href 屬性,JavaScript 的 eval()、setTimeout()、setInterval() 等,都能把字符串做爲代碼運行。若是不可信的數據拼接到字符串中傳遞給這些 API,很容易產生安全隱患,請務必避免。

其餘防禦措施

Content Security Policy

禁止加載外域代碼,防止複雜的攻擊邏輯。

禁止外域提交,網站被攻擊後,用戶的數據不會泄露到外域。

禁止內聯腳本執行(規則較嚴格,目前發現 GitHub 使用)。

禁止未受權的腳本執行(新特性,Google Map 移動版在使用)。

合理使用上報能夠及時發現 XSS,利於儘快修復問題。
複製代碼

輸入內容長度控制

對於不受信任的輸入,都應該限定一個合理的長度。雖然沒法徹底防止 XSS 發生,但能夠增長 XSS 攻擊的難度

其餘安全措施

HTTP-only Cookie: 禁止 JavaScript 讀取某些敏感 Cookie,攻擊者完成 XSS 注入後也沒法竊取此 Cookie。

驗證碼:防止腳本冒充用戶提交危險操做。

XSS攻擊總結

  • 利用模板引擎:開啓模板引擎自帶的 HTML 轉義功能
  • 避免內聯事件
  • 避免拼接 HTML
  • 主動檢測和發現

CSRF攻擊

什麼是CSRF攻擊?

CSRF(Cross-site request forgery)跨站請求僞造:攻擊者誘導受害者進入第三方網站,在第三方網站中,向被攻擊網站發送跨站請求。利用受害者在被攻擊網站已經獲取的註冊憑證,繞事後臺的用戶驗證,達到冒充用戶對被攻擊的網站執行某項操做的目的。

CSRF攻擊的特色

  • 攻擊通常發起在第三方網站,而不是被攻擊的網站。被攻擊的網站沒法防止攻擊發生
  • 攻擊者利用受害者在被攻擊網站的登陸憑證,冒充受害者提交操做,而不是直接竊取數據。
  • 整個過程攻擊者並不能得到登陸憑證,只是冒用
  • 跨站請求能夠用各類方式:圖片URL、超連接、CORS、Form提交等等。部分請求方式能夠直接嵌入在第三方論壇、文章中,難以進行追蹤。

CSRF分類

GET類型的CSRF

<img src="http://bank.example/withdraw?amount=10000&for=hacker" > 
複製代碼

Post類型的CSRF

<form action="http://bank.example/withdraw" method=POST>

    <input type="hidden" name="account" value="xiaoming" />

    <input type="hidden" name="amount" value="10000" />

    <input type="hidden" name="for" value="hacker" />

</form>

<script> document.forms[0].submit(); </script> 
複製代碼

訪問該頁面,表單會自動提交。

連接類型的CSRF

連接類型的CSRF並不常見,比起其餘兩種用戶打開頁面就中招的狀況,這種須要用戶點擊連接纔會觸發。這種類型一般是在論壇中發佈的圖片中嵌入惡意連接,或者以廣告的形式誘導用戶中招,攻擊者一般會以比較誇張的詞語誘騙用戶點擊,例如:

<a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">

  重磅消息!!

  <a/>
複製代碼

CSRF防範

  • 阻止不明外域訪問
  1. 同源檢測
  2. Samesite Cookie
  • 提交時要求附加本域才能獲取的信息
  1. CSRF Token
  2. 雙重Cookie驗證

同源檢測

既然CSRF大多來自第三方網站,那麼咱們就直接禁止外域(或者不受信任的域名)對咱們發起請求。

* Origin Header

* Referer Header
複製代碼
  • 使用Origin Header肯定來源域名
  • 使用Referer Header肯定來源域名

CSRF Token 的防禦策略

  1. 將CSRF Token輸出到頁面

用戶打開頁面的時候,服務器給這個用戶生成一Token,但不能放到cookie中,不然仍是會被攻擊者冒用。因此要存在服務器的session中

  1. 頁面提交的請求攜帶這個Token
  2. 服務器眼睜睜Token是否正確

分佈式校驗

大型網站,使用session存儲CSRF Token會帶來很大壓力。並且如今都是分佈式部署,一個用戶發送的屢次HTTP請求可能不在一臺服務器上,可能會獲取不到session數據,所以分佈式集羣中CSRF Token存儲在Redis之類的公共存儲空間

使用Session存儲,讀取和驗證Token會引發比較大的複雜度和性能問題。

ETP方式

這種方法的Token是一個計算出來的結果,而非隨機生成的字符串。這樣在校驗時無需再去讀取存儲的Token,只用再次計算一次便可。

雙重Cookie驗證

那麼另外一種防護措施是使用雙重提交Cookie。利用CSRF攻擊不能獲取到用戶Cookie的特色,咱們能夠要求Ajax和表單請求攜帶一個Cookie中的值。

  1. 用戶訪問頁面,注入一個cookie
  2. 在前端向後端發起請求,取出cookie,添加到url的參數中
  3. 後端接口驗證

優勢

  • 無需使用Session,適用面更廣,易於實施。

  • Token儲存於客戶端中,不會給服務器帶來壓力。

  • 相對於Token,實施成本更低,能夠在先後端統一攔截校驗,而不須要一個個接口和頁面添加。

缺點

  • Cookie中增長了額外的字段。

  • 若是有其餘漏洞(例如XSS),攻擊者能夠注入Cookie,那麼該防護方式失效。

  • 難以作到子域名的隔離。

  • 爲了確保Cookie傳輸安全,採用這種防護方式的最好確保用整站HTTPS的方式,若是還沒切HTTPS的使用這種方式也會有風險。

Samesite Cookie 屬性

Samesite=Strict

這種稱爲嚴格模式,代表這個 Cookie 在任何狀況下都不可能做爲第三方 Cookie,絕無例外

Set-Cookie: foo=1; Samesite=Strict

Set-Cookie: bar=2; Samesite=Lax

Set-Cookie: baz=3
複製代碼

咱們在 a.com 下發起對 b.com 的任意請求,foo 這個 Cookie 都不會被包含在 Cookie 請求頭中,但 bar 會。舉個實際的例子就是,假如淘寶網站用來識別用戶登陸與否的 Cookie 被設置成了 Samesite=Strict,那麼用戶從百度搜索頁面甚至天貓頁面的連接點擊進入淘寶後,淘寶都不會是登陸狀態,由於淘寶的服務器不會接受到那個 Cookie,其它網站發起的對淘寶的任意請求都不會帶上那個 Cookie。

Samesite=Lax

這種稱爲寬鬆模式,比 Strict 放寬了點限制:假如這個請求是這種請求(改變了當前頁面或者打開了新頁面)且同時是個GET請求,則這個Cookie能夠做爲第三方Cookie。

注意

另一個問題是Samesite的兼容性不是很好,現階段除了重新版Chrome和Firefox支持之外,Safari以及iOS Safari都還不支持,現階段看來暫時還不能普及。

並且,SamesiteCookie目前有一個致命的缺陷:不支持子域。例如,種在topic.a.com下的Cookie,並不能使用a.com下種植的SamesiteCookie。這就致使了當咱們網站有多個子域名時,不能使用SamesiteCookie在主域名存儲用戶登陸信息。每一個子域名都須要用戶從新登陸一次。

僅用於我的整理,參考:

Web安全

相關文章
相關標籤/搜索