1. 程式人生 > 實用技巧 >CSRF攻擊是什麼?如何防範?

CSRF攻擊是什麼?如何防範?

目錄

1、CSRF攻擊是什麼?如何防範?

CSRF(Cross-site request forgery), 中文名稱:跨站請求偽造。攻擊者盜用了你的身份,以你的名義傳送惡意請求。

CSRF能做的事情包括:以你的名義傳送郵件,發訊息,盜取你的賬號,在受害者不知情的情況下,以受害者名義偽造請求傳送給受攻擊站點,從而在受害者並未授權的情況下執行受害者許可權下的各種操作。

2、CSRF攻擊的原理

  • 正常網站A,存在CSRF漏洞;惡意網站B含有攻擊性程式碼,用來對網站A進行攻擊。
  • 正常網站A,有兩個使用者user01(受害者)和user02(攻擊者)。
  • user02(攻擊者)清楚的瞭解網站A,並建立了具有攻擊性的網站B(釣魚網站)。
  • user01(受害者)登入了網站A後,在自身的session未失效的情況下,訪問了惡意網站B.

3、 CSRF攻擊的過程

  • 1.使用者user01通過瀏覽器訪問正常網站A,輸入使用者名稱和密碼請求登入驗證
  • 2.登入驗證通過後,網站A儲存user01的session,並將對應的cookie返回給user01的瀏覽器。這樣user01就可以在網站A執行自身許可權下的各種請求(操作),比如取錢,發表文章,發表評論等
  • 3.user01在未退出網站A的時候,在同一瀏覽器,點選訪問了惡意網站B(釣魚網站),此時user02拿到user01的認證資訊或者登入狀態
  • 4.網站B是user02建立的,user02清楚的知道網站A的工作模式,網站B通過攻擊性程式碼訪問網站A(攜帶的是user01的cookie),執行某些並非user01授意的操作。
  • 5.網站A並不知道這個惡意請求是從網站B發出的,因此,就會根據user01在網站A中具備的相關許可權,執行許可權下的各種操作。這樣,就在user01不知情的情況下,user02假冒了user01,執行了具備user01使用者身份才可以執行的操作

4、CSRF攻擊例項

假設,現在有一個受害者Bob,在網站http://bank.expample/

有一大筆存款。
Bob通過銀行的網站傳送請求http://bank.example/withdraw?account=Bob&amount=100000&to=Bob2,Bob將100000的存款轉賬到Bob2的賬戶下,通常情況下,該請求傳送到銀行網站後,伺服器會先驗證該請求是否來自一個合法的session,該session的使用者Bob已經成功登入
黑客Hack自己在該銀行也有自己的賬戶,他知道銀行轉賬操作的URL。Hack可以自己傳送一個請求給銀行:http://bank.example/withdraw?account=Bob&amount=100000&to=Hack,但是這個請求來自Hack,並非Bob,他不能通過安全驗證,因此該請求不會起作用。這時,Hack香到使用CSRF的攻擊方式,他先自己做一個網站B,在網站B中放入如下程式碼:src="http://bank.example/withdraw?account=Bob&amount=100000&to=Hack",並通過廣告等方式誘使Bob訪問他的網站。當Bob訪問網站B的時候,上述URL就會從Bob的瀏覽器發向銀行,並且這個請求會附帶Bob瀏覽器的cookie一起發現銀行伺服器。當然,大多數情況下,該請求會失敗(session有有效時間),因為銀行網站需要要求Bob的認證資訊。
但是如果Bob當時恰巧剛訪問銀行網站後不久,他的瀏覽器與銀行網站的session尚未過期(比如Bob在一個視窗還未退出銀行網站),而瀏覽器中的cookie就含有Bob的認證資訊,銀行網站的對應session資料還在。
這時悲劇就發生了,這個URL會得到銀行伺服器的響應,錢將從Bob的賬號轉移到Hack的賬號,而Bob並不知情。等事後Bob發現賬戶錢變少了,去銀行查詢流水,卻發現是他自己轉移賬戶的錢,沒有任何被攻擊的痕跡(我搞我自己?人類迷惑行為)
在這個示例中,銀行網站錯誤的認為,這個轉賬時Bob本人執行的

5、CSRF攻擊的物件

從以上的例子可知,CSRF攻擊是黑客藉助受害者的cookie偽造請求,騙取伺服器的信任。黑客所能做的就是給伺服器傳送偽造請求,改變請求時的引數。所以我們要保護的物件是那些可以直接產生資料改變的服務,而對於讀取資料的服務。則不需要進行CSRF的保護。比如銀行系統中轉賬的請求會直接改變賬戶的金額,會遭到CSRF攻擊,需要保護,而查詢餘額是對金額的讀取操作,不會改變資料,無需保護

6、CSRF漏洞檢測

檢測CSRF漏洞是一項比較繁瑣的工作,最簡單的一個方法就是抓取一個正常請求的資料包,去掉Referer欄位後再重新提交,如果該提交還有效,那麼基本上可以確定存在CSRF漏洞。
隨著對CSRF漏洞研究的不斷深入,出現了一些針對CSRF漏洞進行檢測的工具,如CSRFTester,CSRE Request Builder等。

CSRFTester工具的測試原理大概是這樣的,使用代理抓取我們在瀏覽器中訪問過的所有的連線以及所有的表單等資訊,通過在CSRFTester中修改相應的表單等資訊,重新提交,相當於一次偽造客戶端請求,如果修測試的請求成功被網站伺服器接受,則說明存在CSRF漏洞,當然此款工具也可以被用來進行CSRF攻擊

7、防範CSRF攻擊的幾種策略

防範原理:防範CSRF攻擊,其實本質上就是要求網站能夠識別出哪些請求是非正常使用者主動發起的。這就要求我們在請求中嵌入一些額外的授權資料,讓網站伺服器能夠區分出這些未授權的請求。比如在請求引數中加一個欄位,這個欄位的值從登入使用者的Cookie或者頁面中獲取(這個值需要是隨機的,無規律可循)。攻擊者偽造請求的時候無法獲取頁面中與登入使用者有關的一個隨機值或者cookie中的內容的。因此就可以避免這種攻擊

目前防禦CSRF攻擊主要有以下幾種策略

    1. 驗證HTTP Referer欄位
    1. 使用驗證碼(關鍵頁面加上驗證碼驗證,這種方法對使用者不友好,不推薦)
    1. 在請求地址中加入token並驗證
    1. 在HTTP頭中自定義屬性並驗證
驗證HTTP Referer欄位

HTTP頭中的Referer欄位記錄該請求的來源地址。比如訪問http://bank.example/withdraw?account=Bob&amount=100000&to=Hack,使用者必須先登入http://bank.example,然後通過該網站頁面的轉賬按鈕來觸發轉賬事件。這時,該轉賬請求的Referer值就會是轉賬按鈕所在頁面的URL,通常以bank.example域名開頭的地址。

而如果黑客要對銀行網站實施CSRF攻擊,他只能在自己的網站構造請求,當用戶通過黑客的網站傳送請求到銀行網站時,該請求的Referer是指向黑客自己的網站。

因此要防禦CSRF攻擊,銀行只需要對轉賬請求驗證其Referer值,如果以bank.example開頭的域名,則說明該請求是來自銀行網站自己的請求,是合法的,如果Referer是其他網站的話,則有可能是黑客的CSRF攻擊,拒絕該請求。

優點: 簡單易行,只需要在最後給所有敏感的請求統一增加一個攔截器來檢查Referer的值就可以。特別對於當前現有的系統,不需要改變當前系統已有程式碼,沒有風險,簡單便捷

缺點: 這種方法並非萬無一失 。首先,Referer的值是由瀏覽器提供的,但是每個瀏覽器對不Referer的具體實現會有差別,並不能保證瀏覽器自身沒有安全漏洞。驗證Referer的值,把安全性都依賴於瀏覽器來保障,不安全。而已已有一些方法可以篡改Referer值。另外,使用者會因為隱私問題,設定瀏覽器不允許傳送Referer值,這樣服務端的Referer驗證就沒有了意義

在請求地址中新增token並驗證

CSRF 攻擊之所以能夠成功,是因為黑客可以完全偽造使用者的請求,該請求中所有的使用者驗證資訊都存在於 cookie 中,因此黑客可以在不知道這些驗證資訊的情況下直接利用使用者的 cookie來通過安全驗證。

要抵禦 CSRF,關鍵在於在請求中放入黑客所不能偽造的資訊,並且該資訊不存在於 cookie 中。

可以在 HTTP 請求中以引數的形式加入一個隨機產生的 token,並在伺服器端建立一個攔截器來驗證這個 token,如果請求中沒有 token 或者 token 內容不正確,則認為可能是 CSRF 攻擊而拒絕該請求
這種方法要比檢查 Referer 要安全一些,token 可以在使用者登陸後產生並放於 session 之中,然後在每次請求時把 tokensession 中拿出,與請求中的 token 進行比對。

對於 GET 請求,token 將附在請求地址之後,這樣 URL 就變成 http://url?csrftoken=tokenvalue

而對於 POST 請求,要在 form 表單加上:

<input type=”hidden” name=”csrftoken” value=”tokenvalue”/>
該方法也有一個缺點是難以保證 token 本身的安全。

因為即使是 POST 請求的 token,黑客的網站也同樣可以通過 Referer 的值來得到這個 token 值以發動 CSRF 攻擊。這也是一些使用者喜歡手動關閉瀏覽器 Referer 功能的原因。

如果想保證 token 本身的安全,可以考慮使用動態 token,也就是每次請求都使用不同的動態 token。

在 HTTP 頭中自定義屬性並驗證

這種方法也是使用 token 進行驗證,和上一種方法不同的是,這裡並不是把 token 以引數的形式置於 HTTP 請求之中,而是把它放到HTTP 頭中自定義的屬性裡

通過 XMLHttpRequest 物件,可以一次性給所有該類請求加上 csrftoken 這個 HTTP 頭屬性,並把 token 值放入其中。

通過 XMLHttpRequest 請求的地址不會被記錄到瀏覽器的位址列,也不用擔心 token 會透過 Referer 洩露到其他網站中去

然而,這種方法的侷限性非常大XMLHttpRequest 請求通常用於 Ajax 對頁面區域性的非同步重新整理。

並非所有的請求都適合用 Ajax 來發起,而且通過該類請求得到的頁面不能被瀏覽器所記錄,影響前進、後退、重新整理、收藏等操作,給使用者帶來了不便。

另外,對於沒有進行 CSRF 防護的舊系統來說,如果採用這種方法來進行防護,需要把所有請求都改為 XMLHttpRequest 請求,這樣幾乎是要重寫整個網站,工作量無疑是巨大的