密碼學系列之:csrf跨站點請求偽造

flydean發表於2021-03-18

簡介

CSRF的全稱是Cross-site request forgery跨站點請求偽造,也稱為一鍵攻擊或會話劫持,它是對網站的一種惡意利用,主要利用的是已授權使用者對於站點的信任,無辜的終端使用者被攻擊者誘騙提交了他們不希望的Web請求。 惡意網站可以通過多種方式來傳送此類命令。 例如,特製的影像標籤,隱藏的表單和JavaScript XMLHttpRequests都可以在使用者不互動甚至不知情的情況下工作。

如果發生了CSRF攻擊,可能導致客戶端或伺服器資料意外洩漏,會話狀態更改或者修改使用者的資訊。

CSRF的特點

在CSRF的惡意攻擊中,攻擊者的目標是讓被攻擊者在不知不覺中向有許可權訪問的網站提交惡意的web請求。通過對該請求進行精心的設計,使其包含URL引數,Cookie和其他對處理該請求的Web伺服器而言正常顯示的資料。通過儲存在使用者Web瀏覽器中的cookie進行身份驗證的使用者可能會在不知不覺中將HTTP請求傳送到信任該使用者的站點,從而導致不必要的操作。

為什麼會有這樣的攻擊呢?因為對於web瀏覽器來說,它們將在傳送給該域的任何Web請求中自動且無形地包含給定域使用的任何cookie。 CSRF攻擊利用了此屬性,因為瀏覽器發出的任何Web請求都將自動包含受害者登入網站時建立的任何cookie(包括會話cookie和其他cookie)。如果使用者被誘騙通過瀏覽器無意中提交了請求,這些自動包含的cookie將使偽造也能夠通過目標伺服器的認證,從而產生惡意攻擊。

為了生成這樣的攻擊URL,惡意攻擊者需要構造一個可以被執行的web請求,比如在目標頁面上更改帳戶密碼。攻擊者可以將該連結嵌入攻擊者控制範圍內的頁面上。比如它可以嵌入到傳送給受害者的電子郵件中的html影像標籤中,當受害者開啟其電子郵件時,該影像會自動載入。一旦受害者單擊了連結,他們的瀏覽器將自動包含該網站使用的所有cookie,並將請求提交到Web伺服器。 Web伺服器將會執行該惡意請求。

CSRF的歷史

早在2001年,就有人開始使用它來進行攻擊了。不過因為攻擊使用的是使用者自己的IP地址,看起來就像是使用者自己的一個正常的請求,所以很少有直接的攻擊證據。目前知道的比較有名的CSRF攻擊如下:

2006年Netflix爆出了眾多CSRF漏洞,攻擊者可以更改受害者的賬戶收貨地址,從而為攻擊者自己來購買商品。
YouTube在2008年也受到了CSRF的攻擊,這使得任何攻擊者都幾乎可以執行任何使用者的所有操作。
McAfee Secure也曾經受到過CSRF的攻擊,它允許攻擊者更改公司系統。
2018年,一些路由器也受到了CSRF的攻擊,從而能夠修改路由器的DNS設定。

CSRF攻擊的限制

要想達成CSRF攻擊是需要一定的條件的,事實上CSRF攻擊也並不是一個很簡單的事情,必須滿足下面的條件:

  1. 目標web服務沒有檢查請求的referrer header,如果只允許同源請求的話,則無法使用CSRF。
  2. 攻擊者必須在目標站點上找到表單提交檔案,或者發現具有攻擊屬性的URL,該URL會執行某些操作(例如,轉賬或更改受害者的電子郵件地址或密碼)。
  3. 攻擊者必須為所有表單或URL輸入確定正確的值;如果要求它們中的任何一個是攻擊者無法猜到的祕密身份驗證值或ID,則攻擊很可能會失敗(除非攻擊者在他們的猜測中非常幸運)。
  4. 當受害者登入到目標站點時,攻擊者必須誘使受害者進入帶有惡意程式碼的網頁。
  5. 攻擊者只能發出請求,但是無法看到目標站點響應攻擊請求發回給使用者的內容,如果操作具有連續性的話,後續的CSRF攻擊將無法完成。

CSRF攻擊的防範

因為web瀏覽器對不同的HTTP請求處理方式是不同的,所以針對CSRF攻擊的防範跟HTTP請求的方法相關。

在HTTP GET中,使用CSRF攻擊非常簡單,比如將攻擊URL帶入IMG標籤就會自動載入。但是,根據HTTP規範,GET方法不應該被用於修改資料。使用GET進行更新資料操作的應用程式應切換到HTTP POST或使用反CSRF保護。

CSRF的HTTP POST漏洞取決於使用情況:
在最簡單的POST形式中,資料編碼為查詢字串(field1 = value1&field2 = value2),可以使用簡單的HTML形式輕鬆實現CSRF攻擊,這就意味著必須採取反CSRF措施。

如果以其他任何格式(JSON,XML)傳送資料,標準方法是使用XMLHttpRequest發出POST請求,並通過同源策略(SOP)和跨域資源共享(CORS)防止CSRF攻擊。

其他HTTP方法(PUT,DELETE等)只能使用具有同源策略(SOP)和跨域資源共享(CORS)來防止CSRF的XMLHttpRequest請求;但是,在使用Access-Control-Allow-Origin:*標頭明確禁用它們的網站上,這些措施將無效。

下面我們來具體講解幾個防範CSRF的技巧

STP技術

STP的全稱是Synchronizer token pattern。也就是說在所有的HTML表單上包含一個隱藏的token欄位,token是可以由很多種方法來生成,只要保證其隨機性就行了。因為攻擊者無法預測到這個token的值,所以無法進行CSRF攻擊。比如下面的程式碼:

<input type="hidden" name="csrfmiddlewaretoken" value="KbyUmhTLMpYj7CD2di7JKP1P3qmLlkPt" />

STP是相容性最好的,因為它僅依賴HTML,但是每個請求都帶上token會增加程式的複雜性, 由於token是唯一且不可預測的,因此還會強制執行適當的事件順序,這會引發一些可用性的問題(例如使用者開啟多個選項卡)。 可以通過使用每個會話CSRF令牌而不是每個請求CSRF令牌來放寬它。

如果web應用程式主要使用javascript來進行互動的話,可以考慮使用這種方式。

在初次訪問web服務的時候,會在cookie中設定一個隨機令牌,該cookie無法在跨域請求中訪問:

Set-Cookie: csrf_token=i8XNjC4b8KVok4uw5RftR38Wgp2BFwql; Expires=Thu, 23-Jul-2015 10:25:33 GMT; Max-Age=31449600; Path=/; Domain=.wikipedia.org; SameSite=Lax; Secure

在客戶端執行javascript的時候,從cookie中讀取這個token值,並將其複製到隨每個事務請求傳送的自定義HTTP標頭中

X-Csrftoken:i8XNjC4b8KVok4uw5RftR38Wgp2BFwql

伺服器驗證令牌的存在和完整性。因為從惡意檔案或電子郵件執行的JavaScript無法成功讀取cookie值以複製到自定義標頭中。即使將csrf token cookie與惡意請求一起自動傳送,伺服器任然需要有效的X-Csrf-Token頭。

這項技術已經被很多框架實現了,比如Django 和AngularJS,因為令牌在整個使用者會話中保持不變,所以它可以與AJAX應用程式很好地協同工作。

注意,使用這項技術,必須確保同源政策。

這個方法與cookie-to-header方法類似,但不涉及JavaScript,站點可以將CSRF令牌設定為cookie,也可以將其作為每個HTML表單中的隱藏欄位插入。 提交表單後,站點可以檢查cookie令牌是否與表單令牌匹配。 同源策略可防止攻擊者在目標域上讀取或設定Cookie,因此他們無法以其精心設計的形式放置有效令牌。

與同步器模式相比,此技術的優勢在於不需要將令牌儲存在伺服器上。

當伺服器設定cookie時,可以包含一個附加的“ SameSite”屬性,指示瀏覽器是否將cookie附加到跨站點請求。 如果將此屬性設定為“strict”,則cookie僅在相同來源的請求中傳送,從而使CSRF無效。 但是,這需要瀏覽器識別並正確實現屬性,並且還要求cookie具有“Secure”標誌。

Client-side safeguards

瀏覽器本身可以通過為跨站點請求提供預設拒絕策略,來阻止CSRF。比如Mozilla Firefox的RequestPolicy或者Firefox和Google Chrome / Chromium 的uMatrix之類。但是,這可能會嚴重干擾許多網站的正常執行。

有些瀏覽器擴充套件程式如CsFire擴充套件(也適用於Firefox)可以通過從跨站點請求中刪除身份驗證資訊,從而減少對正常瀏覽的影響。

本文已收錄於 http://www.flydean.com/csrf/

最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!

相關文章