Django中如何防范CSRF跨站點(diǎn)請(qǐng)求偽造攻擊的實(shí)現(xiàn)
CSRF概念
CSRF跨站點(diǎn)請(qǐng)求偽造(Cross—Site Request Forgery)。
攻擊者盜用了你的身份,以你的名義發(fā)送惡意請(qǐng)求,對(duì)服務(wù)器來說這個(gè)請(qǐng)求是完全合法的,但是卻完成了攻擊者所期望的一個(gè)操作,比如以你的名義發(fā)送郵件、發(fā)消息,盜取你的賬號(hào),添加系統(tǒng)管理員,甚至于購買商品、虛擬貨幣轉(zhuǎn)賬等。
CSRF攻擊原理以及過程
用戶C打開瀏覽器,訪問受信任網(wǎng)站A,輸入用戶名和密碼請(qǐng)求登錄網(wǎng)站A;
在用戶信息通過驗(yàn)證后,網(wǎng)站A產(chǎn)生Cookie信息并返回給瀏覽器,此時(shí)用戶登錄網(wǎng)站A成功,可以正常發(fā)送請(qǐng)求到網(wǎng)站A;
用戶未退出網(wǎng)站A之前,在同一瀏覽器中,打開一個(gè)TAB頁訪問網(wǎng)站B;
網(wǎng)站B接收到用戶請(qǐng)求后,返回一些攻擊性代碼,并發(fā)出一個(gè)請(qǐng)求要求訪問第三方站點(diǎn)A;
瀏覽器在接收到這些攻擊性代碼后,根據(jù)網(wǎng)站B的請(qǐng)求,在用戶不知情的情況下攜帶Cookie信息,向網(wǎng)站A發(fā)出請(qǐng)求。網(wǎng)站A并不知道該請(qǐng)求其實(shí)是由B發(fā)起的,所以會(huì)根據(jù)用戶C的Cookie信息以C的權(quán)限處理該請(qǐng)求,導(dǎo)致來自網(wǎng)站B的惡意代碼被執(zhí)行。
CSRF攻擊實(shí)例
受害者 Bob 在銀行有一筆存款,通過對(duì)銀行的網(wǎng)站發(fā)送請(qǐng)求 http://bank.example/withdraw?account=bob&amount=1000000&for=bob2可以使 Bob 把 1000000 的存款轉(zhuǎn)到 bob2 的賬號(hào)下。通常情況下,該請(qǐng)求發(fā)送到網(wǎng)站后,服務(wù)器會(huì)先驗(yàn)證該請(qǐng)求是否來自一個(gè)合法的 session,并且該 session 的用戶 Bob 已經(jīng)成功登陸。
黑客 Mallory 自己在該銀行也有賬戶,他知道上文中的 URL 可以把錢進(jìn)行轉(zhuǎn)帳操作。Mallory 可以自己發(fā)送一個(gè)請(qǐng)求給銀行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。但是這個(gè)請(qǐng)求來自 Mallory 而非 Bob,他不能通過安全認(rèn)證,因此該請(qǐng)求不會(huì)起作用。
這時(shí),Mallory 想到使用 CSRF 的攻擊方式,他先自己做一個(gè)網(wǎng)站,在網(wǎng)站中放入如下代碼:src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ”,并且通過廣告等誘使 Bob 來訪問他的網(wǎng)站。當(dāng) Bob 訪問該網(wǎng)站時(shí),上述 url 就會(huì)從 Bob 的瀏覽器發(fā)向銀行,而這個(gè)請(qǐng)求會(huì)附帶 Bob 瀏覽器中的 cookie 一起發(fā)向銀行服務(wù)器。大多數(shù)情況下,該請(qǐng)求會(huì)失敗,因?yàn)樗?Bob 的認(rèn)證信息。但是,如果 Bob 當(dāng)時(shí)恰巧剛訪問他的銀行后不久,他的瀏覽器與銀行網(wǎng)站之間的 session 尚未過期,瀏覽器的 cookie 之中含有 Bob 的認(rèn)證信息。這時(shí),悲劇發(fā)生了,這個(gè) url 請(qǐng)求就會(huì)得到響應(yīng),錢將從 Bob 的賬號(hào)轉(zhuǎn)移到 Mallory 的賬號(hào),而 Bob 當(dāng)時(shí)毫不知情。等以后 Bob 發(fā)現(xiàn)賬戶錢少了,即使他去銀行查詢?nèi)罩荆仓荒馨l(fā)現(xiàn)確實(shí)有一個(gè)來自于他本人的合法請(qǐng)求轉(zhuǎn)移了資金,沒有任何被攻擊的痕跡。而 Mallory 則可以拿到錢后逍遙法外。
Django中如何防范CSRF
Django使用專門的中間件(CsrfMiddleware)來進(jìn)行CSRF防護(hù)。具體的原理如下:
1.它修改當(dāng)前處理的請(qǐng)求,向所有的 POST 表單增添一個(gè)隱藏的表單字段,使用名稱是 csrfmiddlewaretoken ,值為當(dāng)前會(huì)話 ID 加上一個(gè)密鑰的散列值。 如果未設(shè)置會(huì)話 ID ,該中間件將不會(huì)修改響應(yīng)結(jié)果,因此對(duì)于未使用會(huì)話的請(qǐng)求來說性能損失是可以忽略的。
2.對(duì)于所有含會(huì)話 cookie 集合的傳入 POST 請(qǐng)求,它將檢查是否存在 csrfmiddlewaretoken 及其是否正確。 如果不是的話,用戶將會(huì)收到一個(gè) 403 HTTP 錯(cuò)誤。 403 錯(cuò)誤頁面的內(nèi)容是檢測到了跨域請(qǐng)求偽裝。 終止請(qǐng)求。
該步驟確保只有源自你的站點(diǎn)的表單才能將數(shù)據(jù) POST 回來。
另外要說明的是,未使用會(huì)話 cookie 的 POST 請(qǐng)求無法受到保護(hù),但它們也不 需要 受到保護(hù),因?yàn)閻阂饩W(wǎng)站可用任意方法來制造這種請(qǐng)求。為了避免轉(zhuǎn)換非 HTML 請(qǐng)求,中間件在編輯響應(yīng)結(jié)果之前對(duì)它的 Content-Type 頭標(biāo)進(jìn)行檢查。 只有標(biāo)記為 text/html 或 application/xml+xhtml 的頁面才會(huì)被修改。
Django防范CSRF的具體操作
1. 將'django.middleware.csrf.CsrfViewMiddleware'添加到Django的settings.py文件中的MIDDLEWARE_CLASSES列表中(默認(rèn)已經(jīng)添加)。 該中間件必須在 SessionMiddleware 之后執(zhí)行,因此在列表中 CsrfMiddleware 必須出現(xiàn)在SessionMiddleware 之前 (因?yàn)轫憫?yīng)中間件是自后向前執(zhí)行的)。 同時(shí),它也必須在響應(yīng)被壓縮或解壓之前對(duì)響應(yīng)結(jié)果進(jìn)行處理,因此CsrfMiddleware必須在GZipMiddleware之后執(zhí)行。
MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', # Uncomment the next line for simple clickjacking protection: # 'django.middleware.clickjacking.XFrameOptionsMiddleware', )
2. 在使用到POST方法提交FORM的頁面中,添加csrf_token標(biāo)簽,例如:
<form action="." method="post">{% csrf_token %}
3. 在相應(yīng)的view中,確?!癲jango.core.context_processors.csrf” 上下文處理器被正確使用,有兩種方法實(shí)現(xiàn)這一點(diǎn),一是使用RequestContext,它內(nèi)部會(huì)自動(dòng)使用到“django.core.context_processors.csrf”。另一種方法是手動(dòng)使用這個(gè)處理器,示例代碼如下:
from django.core.context_processors import csrf from django.shortcuts import render_to_response def my_view(request): c = {} c.update(csrf(request)) # ... view code here return render_to_response("a_template.html", c)
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python實(shí)現(xiàn)使用卷積提取圖片輪廓功能示例
這篇文章主要介紹了Python實(shí)現(xiàn)使用卷積提取圖片輪廓功能,涉及Python數(shù)值運(yùn)算與圖像處理相關(guān)操作技巧,需要的朋友可以參考下2018-05-05python使用pycharm環(huán)境調(diào)用opencv庫
這篇文章主要介紹了python使用pycharm環(huán)境調(diào)用opencv庫,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02Python實(shí)現(xiàn)將DOC文檔轉(zhuǎn)換為PDF的方法
這篇文章主要介紹了Python實(shí)現(xiàn)將DOC文檔轉(zhuǎn)換為PDF的方法,涉及Python調(diào)用系統(tǒng)win32com組件實(shí)現(xiàn)文件格式轉(zhuǎn)換的相關(guān)技巧,需要的朋友可以參考下2015-07-07python中not not x 與bool(x) 的區(qū)別
這篇文章主要介紹了python中not not x 與 bool(x) 的區(qū)別,我們就來做一個(gè)選擇,就是 not not x 和 bool(x) 用哪個(gè)比較好?下面一起進(jìn)入文章看看吧2021-12-12Python實(shí)現(xiàn)mysql數(shù)據(jù)庫更新表數(shù)據(jù)接口的功能
這篇文章主要給大家介紹了關(guān)于Python如何實(shí)現(xiàn)mysql數(shù)據(jù)庫更新表數(shù)據(jù)接口功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11python的type?hints(類型標(biāo)注、類型注解、類型提示)示例詳解
在Python編程中,類型提示(Type Hints)是一種強(qiáng)大的工具,它能夠幫助開發(fā)者在編寫代碼時(shí)明確表達(dá)變量、函數(shù)參數(shù)和返回值的預(yù)期類型,這篇文章主要給大家介紹了關(guān)于python的type?hints(類型標(biāo)注、類型注解、類型提示)的相關(guān)資料,需要的朋友可以參考下2024-08-08pandas如何篩選某個(gè)列值是否位于某個(gè)列表內(nèi)
這篇文章主要介紹了pandas如何篩選某個(gè)列值是否位于某個(gè)列表內(nèi)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02Tensorflow使用tfrecord輸入數(shù)據(jù)格式
這篇文章主要介紹了Tensorflow使用tfrecord輸入數(shù)據(jù)格式,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-06-06