CSRF 漏洞

相關(guān)課程的線上實(shí)驗(yàn)版本已投遞到實(shí)驗(yàn)樓,實(shí)驗(yàn)樓在線教育平臺(tái)提供非常優(yōu)秀的在線實(shí)驗(yàn)環(huán)境,建議有興趣的朋友可以看看:點(diǎn)擊前往

一、文章介紹

CSRF(Cross-site request forgery)跨站請(qǐng)求偽造,也被稱為 One Click Attack 或者 Session Riding ,通??s寫為 CSRF 或者 XSRF ,是一種對(duì)網(wǎng)站的惡意利用。盡管聽起來像跨站腳本(XSS),但它與 XSS 非常不同, XSS 利用站點(diǎn)內(nèi)的信任用戶,而 CSRF 則通過偽裝來自受信任用戶的請(qǐng)求來利用受信任的網(wǎng)站。與 XSS 攻擊相比, CSRF 攻擊往往不大流行(因此對(duì)其進(jìn)行防范的資源也相當(dāng)稀少)和難以防范,所以被認(rèn)為比 XSS 更具危險(xiǎn)性。

本文要解決以下幾個(gè)問題:

  • 什么是 CSRF 漏洞?

  • CSRF 和 XSS 的區(qū)別?

  • 如何防范 CSRF 漏洞?


二、漏洞簡(jiǎn)介

跨站請(qǐng)求攻擊,簡(jiǎn)單地說,是攻擊者通過一些技術(shù)手段欺騙用戶的瀏覽器去訪問一個(gè)自己曾經(jīng)認(rèn)證過的網(wǎng)站并執(zhí)行一些操作(如發(fā)郵件,發(fā)消息,甚至財(cái)產(chǎn)操作如轉(zhuǎn)賬和購(gòu)買商品)。由于瀏覽器曾經(jīng)認(rèn)證過,所以被訪問的網(wǎng)站會(huì)認(rèn)為是真正的用戶操作而去執(zhí)行。這利用了 web 中用戶身份驗(yàn)證的一個(gè)漏洞:簡(jiǎn)單的身份驗(yàn)證只能保證請(qǐng)求發(fā)自某個(gè)用戶的瀏覽器,卻不能保證請(qǐng)求本身是用戶自愿發(fā)出的。

CSRF 與XSS 區(qū)別:

XSS:    XSS漏洞——構(gòu)造payload——發(fā)送給受害人——受害人點(diǎn)擊打開——攻擊者獲取受害人的cookie——攻擊者使用受害人cookie完成攻擊

CSRF:  CSRF漏洞——構(gòu)造payload——發(fā)送給受害人——受害人點(diǎn)擊打開——受害人執(zhí)行代碼——受害人完成攻擊(不知情)

CSRF攻擊流程:

此處輸入圖片的描述

從上圖可以看出,要完成一次CSRF攻擊,受害者必須依次完成兩個(gè)步驟:

  • 登錄受信任網(wǎng)站A,并在本地生成Cookie。

  • 在不登出A的情況下,訪問危險(xiǎn)網(wǎng)站B

看到這里,你也許會(huì)說:“如果我不滿足以上兩個(gè)條件中的一個(gè),我就不會(huì)受到CSRF的攻擊”。是的,確實(shí)如此,但你不能保證以下情況不會(huì)發(fā)生:

  • 你不能保證你登錄了一個(gè)網(wǎng)站后,不再打開一個(gè)tab頁(yè)面并訪問另外的網(wǎng)站。

  • 你不能保證你關(guān)閉瀏覽器了后,你本地的Cookie立刻過期,你上次的會(huì)話已經(jīng)結(jié)束。

所以 CSRF 是一種較難防御、又危險(xiǎn)極大的漏洞。

三、漏洞原理

3.1 CSRF 漏洞實(shí)例

當(dāng)我們打開或者登陸某個(gè)網(wǎng)站的時(shí)候,瀏覽器與網(wǎng)站所存放的服務(wù)器將會(huì)產(chǎn)生一個(gè)會(huì)話(cookies),在這個(gè)會(huì)話沒有結(jié)束時(shí),你就可以利用你的權(quán)限對(duì)網(wǎng)站進(jìn)行操作。然而,攻擊者就是利用這個(gè)特性,讓受害者觸發(fā)我們構(gòu)造的表單或者語(yǔ)句,然后達(dá)到攻擊者想要達(dá)到的目的。

這是我編寫的一個(gè)簡(jiǎn)單的模擬網(wǎng)站后臺(tái)管理的頁(yè)面,用戶名、密碼都是admin :

此處輸入圖片的描述
此處輸入圖片的描述

一般來說后臺(tái)管理員都具有添加用戶的功能,所以登錄成功之后點(diǎn)擊添加用戶(這里為了方便演示,并沒有讓管理員自定義賬戶名、密碼的功能,而是添加默認(rèn)的賬戶和密碼):

此處輸入圖片的描述

頁(yè)面沒有回顯,但后臺(tái)已經(jīng)成功添加用戶,查看新添加的用戶 :

此處輸入圖片的描述

這時(shí)候如果我們記錄下剛剛添加用戶的網(wǎng)頁(yè)地址,是否無論是哪個(gè)用戶,只要訪問這個(gè)地址就能添加用戶呢?

為了驗(yàn)證這個(gè)想法,我們需要先注銷登錄(清楚cookie信息):


此處輸入圖片的描述

嘗試在瀏覽器輸入之前添加用戶的頁(yè)面地址:localhost/codeaudit/csrf/adduser.php,嘗試直接添加用戶 :

此處輸入圖片的描述

但是并沒有成功,頁(yè)面也自動(dòng)跳轉(zhuǎn)到登錄頁(yè)面,為什么呢?因?yàn)?code>adduser.php頁(yè)面需要驗(yàn)證session信息才能執(zhí)行相應(yīng)操作。

但是有人想到:“既然我們自己不能成功訪問這個(gè)頁(yè)面,能否在管理員不知道的情況下,欺騙他訪問這個(gè)頁(yè)面呢?”,這就是CSRF 漏洞的產(chǎn)生原因。

具體的欺騙方式是:

我們?cè)谌我忭?yè)面新建一個(gè)鏈接,此鏈接連接到的地址就是之前添加用戶的地址:localhost/codeaudit/csrf/adduser.php:

此處輸入圖片的描述

然后通過郵件或其他方式誘使管理員點(diǎn)擊此鏈接(比如偽裝成圖片鏈接),然后就可以在管理員未發(fā)現(xiàn)的情況下添加用戶:

此處輸入圖片的描述

這就是一次利用CSRF漏洞添加后臺(tái)的實(shí)例, 只要用戶(受害者)點(diǎn)擊該鏈接,就完成了一次CSRF攻擊,雖然用戶可能本身并沒有執(zhí)行該操作的意圖。

在實(shí)際情況中,當(dāng)管理員添加用戶時(shí),通常會(huì)自定義用戶名和密碼,而用戶名和密碼一般都是通過get方式直接在url中傳輸,所以我們偽造的連接中也可以自定義我們想用的用戶名和密碼。

四、漏洞防御

4.1 CSRF 漏洞防御策略

在服務(wù)器端防御CSRF攻擊主要有四種策略:

  • 驗(yàn)證HTTP Referer 字段
根據(jù)HTTP協(xié)議,在HTTP頭中有一個(gè)字段叫Referer,它記錄了該HTTP請(qǐng)求的來源地址。在通常情況下,訪問一個(gè)安全受限頁(yè)面的請(qǐng)求必須來自于同一個(gè)網(wǎng)站。比如某銀行的轉(zhuǎn)賬是通過用戶訪問http://bank.test/test?page=10&userID=101&money=10000頁(yè)面完成,用戶必須先登錄bank.test,然后通過點(diǎn)擊頁(yè)面上的按鈕來觸發(fā)轉(zhuǎn)賬事件。當(dāng)用戶提交請(qǐng)求時(shí),該轉(zhuǎn)賬請(qǐng)求的Referer值就會(huì)是轉(zhuǎn)賬按鈕所在頁(yè)面的URL(本例中,通常是以bank. test域名開頭的地址)。而如果攻擊者要對(duì)銀行網(wǎng)站實(shí)施CSRF攻擊,他只能在自己的網(wǎng)站構(gòu)造請(qǐng)求,當(dāng)用戶通過攻擊者的網(wǎng)站發(fā)送請(qǐng)求到銀行時(shí),該請(qǐng)求的Referer是指向攻擊者的網(wǎng)站。因此,要防御CSRF攻擊,銀行網(wǎng)站只需要對(duì)于每一個(gè)轉(zhuǎn)賬請(qǐng)求驗(yàn)證其Referer值,如果是以bank. test開頭的域名,則說明該請(qǐng)求是來自銀行網(wǎng)站自己的請(qǐng)求,是合法的。如果Referer是其他網(wǎng)站的話,就有可能是CSRF攻擊,則拒絕該請(qǐng)求。
  • 在請(qǐng)求地址中添加token并驗(yàn)證
CSRF攻擊之所以能夠成功,是因?yàn)楣粽呖梢詡卧煊脩舻恼?qǐng)求,該請(qǐng)求中所有的用戶驗(yàn)證信息都存在于Cookie中,因此攻擊者可以在不知道這些驗(yàn)證信息的情況下直接利用用戶自己的Cookie來通過安全驗(yàn)證。由此可知,抵御CSRF攻擊的關(guān)鍵在于:在請(qǐng)求中放入攻擊者所不能偽造的信息,并且該信息不存在于Cookie之中。鑒于此,系統(tǒng)開發(fā)者可以在HTTP請(qǐng)求中以參數(shù)的形式加入一個(gè)隨機(jī)產(chǎn)生的token,并在服務(wù)器端建立一個(gè)攔截器來驗(yàn)證這個(gè)token,如果請(qǐng)求中沒有token或者token內(nèi)容不正確,則認(rèn)為可能是CSRF攻擊而拒絕該請(qǐng)求。
  • 在HTTP頭中自定義屬性并驗(yàn)證
自定義屬性的方法也是使用token并進(jìn)行驗(yàn)證,和前一種方法不同的是,這里并不是把token以參數(shù)的形式置于HTTP請(qǐng)求之中,而是把它放到HTTP頭中自定義的屬性里。通過XMLHttpRequest這個(gè)類,可以一次性給所有該類請(qǐng)求加上csrftoken這個(gè)HTTP頭屬性,并把token值放入其中。這樣解決了前一種方法在請(qǐng)求中加入token的不便,同時(shí),通過這個(gè)類請(qǐng)求的地址不會(huì)被記錄到瀏覽器的地址欄,也不用擔(dān)心token會(huì)通過Referer泄露到其他網(wǎng)站。
  • 添加驗(yàn)證碼并驗(yàn)證
在表單中增加一個(gè)隨機(jī)的數(shù)字或字母驗(yàn)證碼,通過強(qiáng)制用戶和應(yīng)用進(jìn)行交互,來有效地遏制CSRF攻擊。

4.2 Token 防御 CSRF 實(shí)例

針對(duì)使用 token 防御 CSRF 攻擊,我這里做一個(gè)簡(jiǎn)單的介紹。

  1. 要使得Token對(duì)于Hacker來說比較難以偽造,我們可以使用偽隨機(jī)數(shù)生成器來構(gòu)造它,然后把它放到服務(wù)器端的session里,并將Token發(fā)給用戶(注意并沒有保存在cookie中);

  2. 當(dāng)用戶提交請(qǐng)求時(shí),服務(wù)器端攔截器將POST請(qǐng)求中的Token提取出來,與session中的Token進(jìn)行比對(duì),相等即執(zhí)行下一步操作。

具體代碼:

# 生成 token
 session_start();
 function set_token(){
     $_SESSION['token'] = md5(time()+rand(1,5000));
 }
# 使用 token 做驗(yàn)證
function check_token(){
    if(isset($_POST['token'])&&$_POST['token'] === $_SESSION['token'])
    {
        return ture;
    }
    else
    {
        return false;
    }
}

可以看到,同時(shí)驗(yàn)證了cookie中的sessionid與POST中的Token。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容