天天看點

讓我們一起來消滅CSRF跨站請求僞造(上)

寫在前面的話

現在已經是2017年了,想必大家一定知道什麼是CSRF(跨站請求僞造)了,因為之前關于這個話題的讨論已經有很多了。這種漏洞已經存在了很多年,社群中也有非常詳細的文檔以及對應的解決方案,目前很多熱門的網站開發架構基本上或多或少都實作了相應的緩解方案。

讓我們一起來消滅CSRF跨站請求僞造(上)

那我們在本系列文章中要讨論什麼呢?請大家先思考以下幾個因素:

遺留應用缺少CSRF保護;

某些架構的内置CSRF防護機制存在缺陷;

應用程式沒有使用已證明安全的架構保護機制;

新的應用程式沒有使用提供了CSRF保護功能的現代架構;

是以,對于目前的Web應用程式來說,CSRF仍然是一個相對普遍存在的安全漏洞。

在這篇文章中,我們首先會跟大家深入分析CSRF的工作機制,以及現代應用程式可以采用的安全措施。接下來,我們會給大家提供一份安全解決方案,同學們可以将其用于自己所開發的應用程式之中(不需要對源代碼進行任何修改)。最後,我們會給大家測試一種針對cookie的新型擴充,如果它能夠成為一種通用标準的話,它将能夠消除絕大多數場景下的跨站腳本漏洞。除此之外,我們在GitHub庫中提供了本系列文章中所要使用到的代碼以及測試樣例,有需要的同學可以自行下載下傳。

了解攻擊機制

簡而言之,CSRF這種漏洞将允許攻擊者強迫目标使用者代表攻擊者發送HTTP請求。這種攻擊主要發生在用戶端(例如Web浏覽器),而在這種場景下目标使用者所發送的應用程式資訊是完全可信的,是以攻擊者就可以成功實作攻擊了。對于這種類型的攻擊,我們需要關注以下三個因素:使用不安全的HTTP verb ,Web浏覽器對cookie的處理、以及跨站腳本漏洞(XSS)。

HTTP标準将verb主要分成了安全的以及不安全的兩大類。安全的verb(GET、HEAD以及OPTIONS)主要用于隻讀操作,使用了這些verb的請求用于傳回與被請求資源有關的資訊,并且不會對伺服器端産生影響。不安全的verb(POST、PUT、PATCH和DELETE)主要用于對資源進行修改、建立和删除操作。但不幸的是,一個HTTP verb本身所要進行的操作是可以被忽略或者被篡改的。

導緻HTTP verb使用不當的主要原因在于浏覽器對HTTP标準的支援存在缺陷,這是一種曆史遺留問題。在XML HTTP Request(XHR)流行起來之前,我們幾乎得依靠特定架構和代碼庫來使用HTTP verb(除了GET和POST之外)。這種限制導緻HTTP verb之間的差別界限變得十分模糊,雖然僅憑這一點并不能建立出CSRF的攻擊場景,但這也讓針對CSRF的保護變得更加難以實作了。對CSRF漏洞“幫助”最大的一個因素,就是浏覽器處理cookie的方式了。

在設計之初,HTTP本身是一種無狀态協定,即一個請求對應一個響應,請求之間不攜帶/交換任何的狀态資訊。為了支援複雜的Web應用程式,cookie就成為了一個維持相關HTTP請求之間狀态的解決方案。浏覽器的全局Cookie可以跨執行個體、視窗和标簽進行共享,使用者需要依賴于Web浏覽器來自動化地給每一個請求發送cookie。由于cookie是可以在浏覽器中進行通路或修改的,并且缺乏反篡改保護,是以請求狀态的儲存任務就轉移到了伺服器管理會話的身上。在這種模型下,伺服器端需要生成一個唯一辨別符并将其存儲到cookie中。每一個浏覽器在發送cookie時都需要發送這個唯一辨別符,而伺服器端就可以根據這種辨別符來判斷會話的有效性了。當會話終止之後,伺服器端會丢棄這個辨別符,之後使用該辨別符的請求都将會被視為無效請求。

現在的主要問題是,浏覽器如何去管理cookie。cookie主要由一系列屬性組成,但其中最重要的是Domain屬性。Domain屬性的功能是将cookie限定到某個比對domain屬性的特定主機範圍内,這是一種用于防止敏感資訊(例如會話識别符)被惡意網站竊取(會話固定攻擊)的安全機制。這裡存在的漏洞是domain屬性并不用遵循同源政策(SOP),它隻會對cookie以及請求中伺服器的domain值進行簡單的對比。這也就意味着,任何不同源的請求隻需要帶有該主機的cookie,就可以向其發送請求了。在這種場景下,隻有安全的以及不安全的HTTP verb能夠得到正确使用,才能確定這種行為是安全的。關于同源政策的更多詳細内容,請參考這篇文檔。

最後一個需要關心的因素,就是跨站腳本(XSS)漏洞。XSS指的是攻擊者控制JavaScript或HTML來給目标使用者呈現DOM内容的能力。如果某個應用程式中存在XSS漏洞的話,那這個應用此時幾乎就無法再抵禦CSRF攻擊了。如果XSS漏洞存在的話,本文所要介紹的以及目前絕大多數應用程式所依賴的應對措施就完全沒有用了。

執行攻擊

既然我們已經了解到了攻擊成功所涉及到的相關因素,我們就可以繼續深入了解CSRF的工作機制了。如果你還沒有搭建好測試環境的話,請現在趕緊按照之前提供的GitHub庫中的方法(參考README文檔)來搭建環境并運作樣本。

我們所要讨論的主要有以下三種CSRF:

資源包含(Resource inclusion)

Form-based

XMLHttpRequest

在絕大多數關于CSRF的示範樣例或者基礎課程之中,資源包含是這種類型是最常見的。這種類型的CSRF允許攻擊者控制一個HTML标簽中包含的資源,例如圖檔、視訊、音頻、對象、以及腳本等等。如果攻擊者能夠影響頁面所加載的URL,則任何包含了遠端資源的标簽都将可以被攻擊者所利用。正如之前所說的,由于缺乏同源檢測,這種攻擊并不需要XSS,而且任何能夠控制目标網站的攻擊者都能夠實作攻擊。這種類型的漏洞僅限适用于GET請求,因為這種請求是浏覽器專門用來請求資源URL的,而且這種漏洞的限制就在于它要求不當使用安全的HTTP verb。

第二種類型是基于表單(form-based)的CSRF,一般出現在安全verb使用正确的情況下。在這種攻擊場景中,攻擊者要自行建立一個表單并欺騙使用者送出該表單。表單中包含一段能夠強迫浏覽器送出該表單的JavaScript代碼段,它不僅全部由隐藏元素組成,而且送出速度非常快,是以目标使用者幾乎無法察覺到。由于浏覽器處理cookie的方式存在問題,是以這種表單可以托管在任何一個網站上,隻要使用者用有效的cookie完成了登入,攻擊就能成功。第二種漏洞配合釣魚攻擊是比較好的。

我們所要讨論的最後一種類型即XMLHttpRequest(XHR),而這種情況是比較少見的,因為利用這種漏洞時所要滿足的條件太多了。由于很多現代Web應用程式都依賴于XHR,是以我們需要花很多事件來建構并實作這種特定的應對措施。由于同源政策的存在,基于XHR的CSRF一般都是通過XSS Payload的形式來利用的。如果沒有跨域資源共享(CORS),XHR将隻能被限制于向特定源發送請求,這樣也就限制了攻擊者托管自己Payload的途徑。這種漏洞的攻擊Payload其實是一種标準XHR,攻擊者可以想辦法将其注入到目标使用者浏覽器的頁面DOM中。

總結

原文釋出時間為:2017-11-02

本文作者:WisFree

本文來自雲栖社群合作夥伴51CTO,了解相關資訊可以關注51CTO。

繼續閱讀