懂你網路系列10之網路安全中的CSRF攻擊

lanyu發表於2021-09-09

一.簡介

CSRF 英文全稱是 Cross-site request forgery,所以又稱為“跨站請求偽造”,也被稱為 one-click attack 或者 session riding,通常縮寫為 CSRF 或者 XSRF, 是一種挾制使用者在當前已登入的Web應用程式上執行非本意的操作的攻擊方法。**跟跨網站指令碼(XSS)相比,XSS 利用的是使用者對指定網站的信任,CSRF 利用的是網站對使用者網頁瀏覽器的信任。 **

對於大多數站點,瀏覽器請求將自動包括與該站點相關聯的任何憑據,例如使用者的會話cookie,IP地址,Windows域憑據等。因此,如果使用者當前已透過站點認證,則該站點將無法區分受害者傳送的偽造請求和受害者傳送的合法請求。

簡單地說,是攻擊者透過一些技術手段欺騙使用者的瀏覽器去訪問一個自己曾經認證過的網站並執行一些操作(如發郵件,發訊息,甚至財產操作如轉賬和購買商品)。由於瀏覽器曾經認證過,所以被訪問的網站會認為是真正的使用者操作而去執行。這利用了web中使用者身份驗證的一個漏洞:簡單的身份驗證只能保證請求發自某個使用者的瀏覽器,卻不能保證請求本身是使用者自願發出的。

二.CSRF攻擊方式

下面先看一個CSRF經典攻擊例子,使用者A透過銀行提供的URL地址進行轉賬戶操作:
圖片描述
使用者A透過GET向銀行站點發起請求,此時的使用者A已經是被認證的狀態了,它的瀏覽器中的Cookie快取著已經認證的會話ID(這是1步驟)

駭客在另一個網站(第三方站點),放置上圖中隱藏在圖片資源中的惡意轉賬需求的連結。如果使用者A訪問了這個第三方的站點(這是步驟2),由於他之前剛訪問銀行站點不久,登入的資訊尚未過期,此時銀行站點對使用者瀏覽器是充分信任的,無論啥請求照單全收,頁面載入時,瀏覽器就自動發起了img中資源請求,銀行站點無法分辨出是否是使用者A的真實操作,因此用A損失了1000刀,心好疼啊!

1.自動發起GET請求的CSRF

從上述的例子可以知道,駭客實施的攻擊方式是自動發起GET請求,這同時也是駭客最簡易和常用的方式,這種惡意的網址可以有很多種形式,藏身於網頁中的許多地方,例如可以插入url的一些地方

<img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="">

2.自動發起POST請求的CSRF

除了自動發起get請求之外,有些站點伺服器介面使用的POST方法,此時駭客可以在該站點上潛伏偽造POST請求,一般在論壇,部落格等任何使用者生成內容的網站中都可能是攻擊發源地。當使用者訪問駭客的站點的,就會自動觸發POST請求,如自動觸發表表單提交:

<html>
<body>
<form  class="hacker" action="" method=POST>
    <input type="hidden" name="account" value="使用者A" />
    <input type="hidden" name="for" value="hacker" />
		<input type="hidden" name="amount" value="1000" />
</form>
<script> document.getElmentsByClassName("hacker").submit(); </script> 
</body>
</html>

3.誘導使用者點選連結的CSRF

如下圖,所示,真的陌生網站連結不要隨便點,尤其是關乎錢,要仔細看,有些網站偽裝太像了。
圖片描述
同以上兩個請求類似,一旦你點選圖中領獎的連結,那麼你很可能就訪問到了駭客站點,那裡預設了一個圈套,等你去觸發,從而造成你的財務上的損失。

三.防止CSRF攻擊策略

以上了解到了三種駭客經常採用的攻擊方式,根據去其攻擊流程,可以發現以CSRF攻擊的特徵,想要成功實施一次CSRF必須具備以下幾點特徵:
CSRF的特徵:

  • 使用者登入過目標站點,獲得過身份認證並且在瀏覽器上保持著該站點的登入狀態
  • 使用者需要訪問一個第三方站點,一般是駭客站點,論壇等,進而發起跨站請求。
  • 目標站點存在一定的CSRF漏洞
  • 攻擊者並不能透過CSRF攻擊來直接獲取使用者的賬戶控制權,也不能直接竊取使用者的任何資訊,僅冒用。

具備了以上條件後,CSRF攻擊就開始進行了,前面提到過跟跨網站指令碼(XSS)相比,XSS 利用的是使用者對指定網站的信任,CSRF 利用的是網站對使用者網頁瀏覽器的信任,對伺服器發起攻擊,被攻擊的伺服器是是可以從阻斷攻擊,或者正面剛,提高自身的攻擊能力來提高安全性,主要有以下幾個主流的方法:

1.利用Cookie的SameSite屬性

該SameSite屬性使伺服器要求cookie不應與跨站點請求一起傳送(該站點由可註冊域定義),這為跨站點請求偽造攻擊(CSRF)提供了一些保護。

從上述的例子CSRF攻擊中一個特徵就是,駭客會利用使用者未過期的登入狀態,即使用者瀏覽器中Cookie快取的已經認證的會話ID.來發起CSRF攻擊

要找阻止駭客透過冒用使用者登入資訊進行CRSF攻擊,就要在Cookie這個關鍵字上面施加一些手段

SameSite屬性主要做兩件事,第一個就是控制跨站點訪問,第二就是保證同一站點的穩定安全訪問。CSRF攻擊都是從第三方站點發起了,在瀏覽器分辨不出好壞請求時,透過一些屬性值可以有效限制Cookie的傳送。如在http相應頭中:

Set-Cookie: mykey=myvalue; SameSite=Strict

它有三個可能的值:Strict,Lax,和None。

  • Strict 最為嚴格:使用Strict,Cookie僅傳送到與它相同的URL。例如你在登入微薄後,如果其用來認證客戶的登入狀態的Cookie被設定成了Samesite=Strict,當你從其他頁面,比如說百度,qq上獲取連結點選進入微薄的時候,你的微博是不會處於登入狀態的,因為微博這個站點(伺服器),不會接受你一個來自百度,qq頁面(第三方站點)的Cookie,就好像第一次來一樣,就是個路人。
  • Lax:Lax不同之處在於使用者何時從外部站點導航至URL,例如透過連結進行導航; 但如果在第三方站點中使用 Post 方法, 或者透過 img、iframe 等標籤載入的 URL,這些場景都不會攜帶 Cookie
  • None:對跨站點請求沒有任何限制。

值得注意的是瀏覽器正在遷移,以將Cookie設定為SameSite=Lax。但是並非所有的預設瀏覽器都是這樣,如果需要跨域傳送cookie,需要顯式的設定None屬性值選擇退出SameSite限制。還必須將Secure屬性新增到SameSite=None cookies中。如:

Set-Cookie: mykey=myvalue; SameSite=none;Secure

對於防範 CSRF 攻擊,根據具體的應用場景將一些些關鍵的 Cookie 設定為 Strict ,Lax 或者None模式,這樣在跨站點請求時,這些關鍵的 Cookie 就不會被髮送到伺服器,從而使得駭客的 CSRF 攻擊失效。

2.檢查Referer和Origin 屬性

HTTP頭中有一個Referer欄位,這個欄位用以標明請求來源於哪個地址。在處理敏感資料請求時,通常來說,Referer欄位應和請求的地址位於同一域名下。

以上文銀行操作為例,Referer欄位地址通常應該是轉賬按鈕所在的網頁地址,應該也位於之下。而如果是CSRF攻擊傳來的請求,Referer欄位會是包含惡意網址的地址,不會位於之下,這時候伺服器就能識別出惡意的訪問

這種辦法簡單易行,工作量低,僅需要在關鍵訪問處增加一步校驗。但這種辦法也有其侷限性,因其完全依賴瀏覽器傳送正確的Referer欄位。

雖然http協議對此欄位的內容有明確的規定,但並無法保證來訪的瀏覽器的具體實現,亦無法保證瀏覽器沒有安全漏洞影響到此欄位。並且也存在攻擊者攻擊某些瀏覽器,篡改其Referer欄位的可能。所以瀏覽器提供給開發者一個選項,可以不用上傳 Referer 值,可參考具體使用參考

因此標準委員會又制定了Origin 屬 性,請求首部欄位 Origin 指示了請求來自於哪個站點。該欄位僅指示伺服器名稱,並不包含任何路徑資訊(處於安全考慮)。該首部用於 CORS 請求(XMLHttpRequest、Fecth )或者 POST 請求。除了不包含路徑資訊,該欄位與 Referer 首部欄位相似。例如

Origin: https://developer.mozilla.org

伺服器的策略是優先判斷 Origin,如果請求頭中沒有包含 Origin 屬性,再根據實際 情況判斷是否使用 Referer 值。

3.新增校驗token

由於CSRF的本質在於攻擊者欺騙使用者去訪問自己設定的地址,所以如果要求在訪問敏感資料請求時,要求使用者瀏覽器提供不儲存在cookie中,並且攻擊者無法偽造的資料作為校驗,那麼攻擊者就無法再執行CSRF攻擊.主要分為以下兩步:

**第一步: **這種資料通常是窗體中的一個資料項。伺服器將其生成並附加在窗體中,其內容是一個偽隨機數。當客戶端透過窗體提交請求時,這個偽隨機數也一併提交上去以供校驗。例如透過以下函式去生成:

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i].trim();
            //這個cookie字串是否以我們想要的名稱開頭?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');

**第二步:**正常的訪問時,客戶端瀏覽器能夠正確得到並傳回這個偽隨機數,而透過CSRF傳來的欺騙性攻擊中,攻擊者無從事先得知這個偽隨機數的值,服務端就會因為校驗token的值為空或者錯誤,拒絕這個可疑請求。

小結

應該遵循以下原則來防禦CSRF
具體方式見

  • 檢查您的框架是否具有內建CSRF保護並使用它
    • 如果框架沒有內建的CSRF保護,則將CSRF令牌新增到所有狀態更改請求(導致在站點上執行操作的請求),並在後端對其進行驗證
  • 始終對會話cookie 使用SameSite Cookie屬性
  • 在“深度緩解”部分中實施至少一項來自防禦的緩解
    • 使用自定義請求標頭
    • 使用標準標題驗證來源
    • 使用雙重提交Cookie
  • 考慮為高度敏感的操作實施基於使用者互動的保護
  • 請記住,任何跨站點指令碼(XSS)都可以用來擊敗所有CSRF緩解技術!
  • 有關如何防止XSS缺陷的詳細指南,
  • 不要將GET請求用於狀態更改操作。
    • 如果出於任何原因這樣做,則還必須保護這些資源免受CSRF的侵害

參考資料:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2035/viewspace-2825563/,如需轉載,請註明出處,否則將追究法律責任。

相關文章