前端面試查漏補缺--(七) XSS攻擊與CSRF攻擊

shotCat發表於2019-02-23

前言

本系列最開始是為了自己面試準備的.後來發現整理越來越多,差不多有十二萬字元,最後決定還是分享出來給大家.

為了分享整理出來,花費了自己大量的時間,起碼是隻自己用的三倍時間.如果喜歡的話,歡迎收藏,關注我!謝謝!

文章連結

合集篇:

前端面試查漏補缺--Index篇(12萬字元合集) 包含目前已寫好的系列其他十幾篇文章.後續新增值文章不會再在每篇新增連結,強烈建議議點贊,關注合集篇!!!!,謝謝!~

後續更新計劃

後續還會繼續新增設計模式,前端工程化,專案流程,部署,閉環,vue常考知識點 等內容.如果覺得內容不錯的話歡迎收藏,關注我!謝謝!

求一份內推

目前本人也在準備跳槽,希望各位大佬和HR小姐姐可以內推一份靠譜的武漢 前端崗位!郵箱:bupabuku@foxmail.com.謝謝啦!~

XSS攻擊

什麼是 XSS

Cross-Site Scripting(跨站指令碼攻擊)簡稱 XSS,是一種程式碼注入攻擊。攻擊者通過在目標網站上注入惡意指令碼,使之在使用者的瀏覽器上執行。利用這些惡意指令碼,攻擊者可獲取使用者的敏感資訊如 Cookie、SessionID 等,進而危害資料安全。

所以,網頁上哪些部分會引起XSS攻擊?簡單來說,任何可以輸入的地方都有可能引起,包括URL!

XSS 常見的注入方法:

  • 在 HTML 中內嵌的文字中,惡意內容以 script 標籤形成注入。
  • 在內聯的 JavaScript 中,拼接的資料突破了原本的限制(字串,變數,方法名等)。
  • 在標籤屬性中,惡意內容包含引號,從而突破屬性值的限制,注入其他屬性或者標籤。
  • 在標籤的 href、src 等屬性中,包含 javascript: (偽協議)等可執行程式碼。
  • 在 onload、onerror、onclick 等事件中,注入不受控制程式碼。
  • 在 style 屬性和標籤中,包含類似 background-image:url("javascript:..."); 的程式碼(新版本瀏覽器已經可以防範)。
  • 在 style 屬性和標籤中,包含類似 expression(...) 的 CSS 表示式程式碼(新版本瀏覽器已經可以防範)。

XSS 攻擊的分類

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

儲存型 XSS

儲存型 XSS 的攻擊步驟:

  1. 攻擊者將惡意程式碼提交到目標網站的資料庫中。
  2. 使用者開啟目標網站時,網站服務端將惡意程式碼從資料庫取出,拼接在 HTML 中返回給瀏覽器。
  3. 使用者瀏覽器接收到響應後解析執行,混在其中的惡意程式碼也被執行。
  4. 惡意程式碼竊取使用者資料併傳送到攻擊者的網站,或者冒充使用者的行為,呼叫目標網站介面執行攻擊者指定的操作。

儲存型 XSS(又被稱為永續性XSS)攻擊常見於帶有使用者儲存資料的網站功能,如論壇發帖、商品評論、使用者私信等。

它是最危險的一種跨站指令碼,相比反射型XSS和DOM型XSS具有更高的隱蔽性,所以危害更大,因為它不需要使用者手動觸發任何允許使用者儲存資料的web程式都可能存在儲存型XSS漏洞,當攻擊者提交一段XSS程式碼後,被伺服器端接收並儲存,當所有瀏覽者訪問某個頁面時都會被XSS

反射型 XSS

反射型 XSS 的攻擊步驟:

  1. 攻擊者構造出特殊的 URL,其中包含惡意程式碼。
  2. 使用者開啟帶有惡意程式碼的 URL 時,網站服務端將惡意程式碼從 URL 中取出,拼接在 HTML 中返回給瀏覽器。
  3. 使用者瀏覽器接收到響應後解析執行,混在其中的惡意程式碼也被執行。
  4. 惡意程式碼竊取使用者資料併傳送到攻擊者的網站,或者冒充使用者的行為,呼叫目標網站介面執行攻擊者指定的操作。

反射型 XSS 跟儲存型 XSS 的區別是:儲存型 XSS 的惡意程式碼存在資料庫裡,反射型 XSS 的惡意程式碼存在 URL 裡。

反射型 XSS (也被稱為非永續性XSS)漏洞常見於通過 URL 傳遞引數的功能,如網站搜尋、跳轉等。

由於需要使用者主動開啟惡意的 URL 才能生效,攻擊者往往會結合多種手段誘導使用者點選。

POST 的內容也可以觸發反射型 XSS,只不過其觸發條件比較苛刻(需要構造表單提交頁面,並引導使用者點選),所以非常少見。

DOM 型 XSS

DOM 型 XSS 的攻擊步驟:

  1. 攻擊者構造出特殊的 URL,其中包含惡意程式碼。
  2. 使用者開啟帶有惡意程式碼的 URL。
  3. 使用者瀏覽器接收到響應後解析執行,前端 JavaScript 取出 URL 中的惡意程式碼並執行。
  4. 惡意程式碼竊取使用者資料併傳送到攻擊者的網站,或者冒充使用者的行為,呼叫目標網站介面執行攻擊者指定的操作。

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

注意:
DOM通常代表在html、xhtml和xml中的物件,使用DOM可以允許程式和指令碼動態的訪問和更新文件的內容、結構和樣式。它不需要伺服器解析響應的直接參與,觸發XSS靠的是瀏覽器端的DOM解析,所以防範DOM型XSS完全就是前端的責任,必須注意!!!

對比:

型別 儲存區 插入點
儲存型 XSS 後端資料庫 HTML
反射型 XSS URL HTML
DOM 型 XSS 後端資料庫/前端儲存/URL 前端 JavaScript

防禦XSS

只要有輸入資料的地方,就可能存在 XSS 危險。

常用防範方法

  • httpOnly: 在 cookie 中設定 HttpOnly 屬性後,js指令碼將無法讀取到 cookie 資訊。

  • 輸入過濾: 一般是用於對於輸入格式的檢查,例如:郵箱,電話號碼,使用者名稱,密碼……等,按照規定的格式輸入。不僅僅是前端負責,後端也要做相同的過濾檢查。因為攻擊者完全可以繞過正常的輸入流程,直接利用相關介面向伺服器傳送設定。

  • 轉義 HTML: 如果拼接 HTML 是必要的,就需要對於引號,尖括號,斜槓進行轉義,但這還不是很完善.想對 HTML 模板各處插入點進行充分的轉義,就需要採用合適的轉義庫.(可以看下這個,還是中文的)

    function escape(str) {
      str = str.replace(/&/g, '&')
      str = str.replace(/</g, '&lt;')
      str = str.replace(/>/g, '&gt;')
      str = str.replace(/"/g, '&quto;')
      str = str.replace(/'/g, '&#39;')
      str = str.replace(/`/g, '&#96;')
      str = str.replace(/\//g, '&#x2F;')
      return str
    }
    複製程式碼
  • 白名單: 對於顯示富文字來說,不能通過上面的辦法來轉義所有字元,因為這樣會把需要的格式也過濾掉。這種情況通常採用白名單過濾的辦法,當然也可以通過黑名單過濾,但是考慮到需要過濾的標籤和標籤屬性實在太多,更加推薦使用白名單的方式。

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

儲存型和反射型 XSS 都是在服務端取出惡意程式碼後,插入到響應 HTML 裡的,攻擊者刻意編寫的“資料”被內嵌到“程式碼”中,被瀏覽器所執行。

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

  • 改成純前端渲染,把程式碼和資料分隔開。
  • 對 HTML 做充分轉義。

HTML轉義前面已經說過,這裡僅僅談談純前端渲染

純前端渲染的過程:

  1. 瀏覽器先載入一個靜態 HTML,此 HTML 中不包含任何跟業務相關的資料。
  2. 然後瀏覽器執行 HTML 中的 JavaScript。
  3. JavaScript 通過 Ajax 載入業務資料,呼叫 DOM API 更新到頁面上。

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

但純前端渲染還需注意避免 DOM 型 XSS 漏洞(例如 onload 事件和 href 中的 javascript:xxx 等,請參考下文”預防 DOM 型 XSS 攻擊“部分)。

在很多內部、管理系統中,採用純前端渲染是非常合適的。但對於效能要求高,或有 SEO 需求的頁面,我們仍然要面對拼接 HTML 的問題,這時就需要對HTML進行充分的轉義。

預防 DOM 型 XSS 攻擊

DOM 型 XSS 攻擊,實際上就是網站前端 JavaScript程式碼本身不夠嚴謹,把不可信的資料當作程式碼執行了。

在使用 .innerHTML.outerHTMLdocument.write() 時要特別小心,不要把不可信的資料作為 HTML 插到頁面上,而應儘量使用 .textContent.setAttribute() 等。

如果用 Vue/React 技術棧,並且不使用 v-html/dangerouslySetInnerHTML 功能,就在前端 render 階段避免 innerHTMLouterHTML 的 XSS 隱患。

DOM 中的內聯事件監聽器,如 locationonclickonerroronloadonmouseover 等,<a> 標籤的 href 屬性,JavaScript 的 eval()setTimeout()setInterval() 等,都能把字串作為程式碼執行。如果不可信的資料拼接到字串中傳遞給這些 API,很容易產生安全隱患,請務必避免。

<!-- 內聯事件監聽器中包含惡意程式碼 -->
<img onclick="UNTRUSTED" onerror="UNTRUSTED" src="data:image/png,">

<!-- 連結內包含惡意程式碼 -->
<a href="UNTRUSTED">1</a>

<script>
// setTimeout()/setInterval() 中呼叫惡意程式碼
setTimeout("UNTRUSTED")
setInterval("UNTRUSTED")

// location 呼叫惡意程式碼
location.href = 'UNTRUSTED'

// eval() 中呼叫惡意程式碼
eval("UNTRUSTED")
</script>
複製程式碼

CSRF 跨站點請求偽造

什麼是 CSRF

跨站請求偽造(英語:Cross-site request forgery),也被稱為 one-click attack 或者 session riding,通常縮寫為 CSRF 或者 XSRF, 是一種挾制使用者在當前已登入的 Web 應用程式上執行非本意的操作的攻擊方法。如:攻擊者誘導受害者進入第三方網站,在第三方網站中,向被攻擊網站傳送跨站請求。利用受害者在被攻擊網站已經獲取的註冊憑證,繞過後臺的使用者驗證,達到冒充使用者對被攻擊的網站執行某項操作的目的。

CSRF攻擊流程

下圖引自這位大佬的淺談CSRF攻擊方式,感謝!

簡而言之:網站過分相信使用者

從上圖可以看出,要完成一次CSRF攻擊,受害者必須依次完成兩個步驟:

  • 1.登入受信任網站A,並在本地生成Cookie。
  • 2.在不登出A的情況下,訪問危險網站B。

看到這裡,你也許會說:“如果我不滿足以上兩個條件中的一個,我就不會受到CSRF的攻擊”。是的,確實如此,但你不能保證以下情況不會發生:

  • 1.你不能保證你登入了一個網站後,不再開啟一個tab頁面並訪問另外的網站。
  • 2.你不能保證你關閉瀏覽器了後,你本地的Cookie立刻過期,你上次的會話已經結束。(事實上,關閉瀏覽器不能結束一個會話,但大多數人都會錯誤的認為關閉瀏覽器就等於退出登入/結束會話了......)
  • 3.上圖中所謂的攻擊網站,可能是一個存在其他漏洞的可信任的經常被人訪問的網站。

常見的CSRF攻擊型別

  • GET型別的CSRF

GET型別的CSRF利用非常簡單,只需要一個HTTP請求,一般會這樣利用:

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

在受害者訪問含有這個img的頁面後,瀏覽器會自動向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker發出一次HTTP請求。bank.example就會收到包含受害者登入資訊的一次跨域請求。

  • POST型別的CSRF

這種型別的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> 
複製程式碼

訪問該頁面後,表單會自動提交,相當於模擬使用者完成了一次POST操作。

POST型別的攻擊通常比GET要求更加嚴格一點,但仍並不複雜。任何個人網站、部落格,被黑客上傳頁面的網站都有可能是發起攻擊的來源,後端介面不能將安全寄託在僅允許POST上面

  • 連結型別的CSRF

連結型別的CSRF並不常見,比起其他兩種使用者開啟頁面就中招的情況,這種需要使用者點選連結才會觸發。這種型別通常是在論壇中釋出的圖片中嵌入惡意連結,或者以廣告的形式誘導使用者中招,攻擊者通常會以比較誇張的詞語誘騙使用者點選,例如:

  <a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">
  重磅訊息!!
  <a/>
複製程式碼

CSRF的特點

  • 攻擊一般發起在第三方網站,而不是被攻擊的網站。被攻擊的網站無法防止攻擊發生。
  • 攻擊利用受害者在被攻擊網站的登入憑證,冒充受害者提交操作;而不是直接竊取資料。
  • 整個過程攻擊者並不能獲取到受害者的登入憑證,僅僅是“冒用”。
  • 跨站請求可以用各種方式:圖片URL、超連結、CORS、Form提交等等。部分請求方式可以直接嵌入在第三方論壇、文章中,難以進行追蹤。

CSRF通常是跨域的,因為外域通常更容易被攻擊者掌控。但是如果本域下有容易被利用的功能,比如可以發圖和連結的論壇和評論區,攻擊可以直接在本域下進行,而且這種攻擊更加危險。

CSRF與 XSS 區別

  • 通常來說 CSRF 是由 XSS 實現的,CSRF 時常也被稱為 XSRF(CSRF 實現的方式還可以是直接通過命令列發起請求等)。
  • 本質上講,XSS 是程式碼注入問題,CSRF 是 HTTP 問題。 XSS 是內容沒有過濾導致瀏覽器將攻擊者的輸入當程式碼執行。CSRF 則是因為瀏覽器在傳送 HTTP 請求時候自動帶上 cookie,而一般網站的 session 都存在 cookie裡面(Token驗證可以避免)。

防禦

  • 驗證碼;強制使用者必須與應用進行互動,才能完成最終請求。此種方式能很好的遏制 csrf,但是使用者體驗比較差。

  • Referer check;請求來源限制,此種方法成本最低,但是並不能保證 100% 有效,因為伺服器並不是什麼時候都能取到 Referer,而且低版本的瀏覽器存在偽造 Referer 的風險。

  • token;token 驗證的 CSRF 防禦機制是公認最合適的方案。(具體可以檢視本系列前端鑑權中對token有詳細描述)若網站同時存在 XSS 漏洞的時候,這個方法也是空談。

其他更詳細的防禦方法可以檢視: 前端安全系列之二:如何防止CSRF攻擊?

感謝及參考

相關文章