詳解python?flask是如何預(yù)防CSRF攻擊
CSRF攻擊防范
詳述CSRF(Cross-site request forgery),中文名稱:跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF。
攻擊者通過HTTP請求將數(shù)據(jù)傳送到服務(wù)器,從而盜取回話的cookie。盜取會話cookie之后,攻擊者不僅可以獲取用戶的信息,還可以修改該cookie關(guān)聯(lián)的賬戶信息。
跨站請求攻擊,簡單地說,是攻擊者通過一些技術(shù)手段欺騙用戶的瀏覽器去訪問一個自己曾經(jīng)認(rèn)證過的網(wǎng)站并運行一些操作(如發(fā)郵件,發(fā)消息,甚至財產(chǎn)操作如轉(zhuǎn)賬和購買商品)。由于瀏覽器曾經(jīng)認(rèn)證過,所以被訪問的網(wǎng)站會認(rèn)為是真正的用戶操作而去運行。這利用了web中用戶身份驗證的一個漏洞:簡單的身份驗證只能保證請求發(fā)自某個用戶的瀏覽器,卻不能保證請求本身是用戶自愿發(fā)出的。
CSRF防范方式一:
同源檢測
Cookie的同源和瀏覽器的同源策略有所區(qū)別:
瀏覽器同源策略:協(xié)議、域名和端口都相同即同源;
- Cookie同源策略:域名相同即同源;
在HTTP協(xié)議中,每個異步請求都會攜帶兩個header,用來標(biāo)記來源域名: - Origin Header
- Referer Header
這兩個Header在瀏覽器發(fā)起請求時,大多數(shù)情況會自動帶上,并且不能由前端修改,服務(wù)器接收到后可以根據(jù)這兩個Header確定來源的域名;
特殊情況: 如果Origin和Referer都不存在,建議直接進(jìn)行阻止,特別是如果您沒有使用隨機CSRF Token(參考下方)作為第二次檢查。
另外,CSRF大多數(shù)情況下來自第三方域名,但并不能排除本域發(fā)起。如果攻擊者有權(quán)限在本域發(fā)布評論(含鏈接、圖片等),那么它可以直接在本域發(fā)起攻擊,這種情況下同源策略無法達(dá)到防護(hù)的作用。
CSRF防范方式二:
添加校驗token
由于CSRF的本質(zhì)在于攻擊者欺騙用戶去訪問自己設(shè)置的地址,所以如果要求在訪問敏感數(shù)據(jù)請求時,要求用戶瀏覽器提供不保存在cookie中,并且攻擊者無法偽造的數(shù)據(jù)作為校驗,那么攻擊者就無法再運行CSRF攻擊。這種數(shù)據(jù)通常是窗體中的一個數(shù)據(jù)項。服務(wù)器將其生成并附加在窗體中,其內(nèi)容是一個偽隨機數(shù)。當(dāng)客戶端通過窗體提交請求時,這個偽隨機數(shù)也一并提交上去以供校驗。正常的訪問時,客戶端瀏覽器能夠正確得到并傳回這個偽隨機數(shù),而通過CSRF傳來的欺騙性攻擊中,攻擊者無從事先得知這個偽隨機數(shù)的值,服務(wù)端就會因為校驗token的值為空或者錯誤,拒絕這個可疑請求
CSRF: 跨域請求偽造攻擊。flask預(yù)防CSRF攻擊需要下載包,flask_wtf。這個就是基于token校驗來防范CSRF攻擊的。
插件下載
pip install flask_wtf
flask_wtf本身提供了生成表單HTML頁面的功能(基于wtforms提供),常用于開發(fā)前后端不分離的表單頁面,同時Flask-wtf 擴展模塊還提供了一套完善的 csrf 防護(hù)體系,對于我們開發(fā)者來說,使用flask_wtf模塊就可以非常簡單解決CSRF攻擊問題。
工作流程
1 在表單響應(yīng)的頁面中加入{% csrf_token %}標(biāo)簽,那么在進(jìn)行模板渲染是會生成如下標(biāo)簽
<input type="hidden" name="csrfmiddlewaretoken" value="ppwN8yg1wVEyXDxtMpVIrc4zV3gHiDKKb9rwGPLaSGRc0HKhXAwpNrKjGDUHIxjj">
2 并且在響應(yīng)還有這個{% csrf_token %}標(biāo)簽的頁面時,會添加cookie鍵值對,如下
csrftoken:lsMQeJgVbIKKxlfz6umgYM8WOWx1Njr77cHzM0L4xtXoApsnhFXXk1OGzwb1dd0G
3 當(dāng)用戶從該頁面提交數(shù)據(jù)時,會攜帶csrfmiddlewaretoken:ppwN8yg1wVEyXDxtMpVIrc4zV3gHiDKKb9rwGPLaSGRc0HKhXAwpNrKjGDUHIxjj和cookie鍵值對
4 取出cookie中的csrftoken值和請求數(shù)據(jù)部分的csrfmiddlewaretoken的值,兩者進(jìn)行比較,這個隨機字符串叫做token字符串.flask如果在請求數(shù)據(jù)部分找tokne值,如果這個鍵對應(yīng)的值和cookie中csrftoken對應(yīng)的值相同,也能通過認(rèn)證.
具體配置
設(shè)置應(yīng)用程序的 secret_key,用于加密生成的 csrf_token 的值
#1. session加密的時候已經(jīng)配置過了.如果沒有在配置項中設(shè)置,則如下: app.secret_key = "#此處可以寫隨機字符串#" #2. 也可以寫在配置類中。 class Config(object): DEBUG = True SECRET_KEY = "dsad32DASSLD*13%^32" """加載配置""" app.config.from_object(Config)
導(dǎo)入 flask_wtf 中的 CSRFProtect類,進(jìn)行初始化,并在初始化的時候關(guān)聯(lián) app
# 方式1: from flask_wtf import CSRFProtect csrf = CSRFProtect() # 這塊代碼可能在文件中。 app = Flask(import_name=__name__, template_folder="templates") # 項目配置代碼之后 csrf.init_app(app) # 避免出現(xiàn)引用導(dǎo)包,所以提供了init_app的用法 # 方式2: # from flask_wtf import CSRFProtect # app = Flask(import_name=__name__, template_folder="templates") # 項目配置代碼之后 # CSRFProtect(app)
完整視圖代碼
from flask import Flask, render_template from flask_wtf import CSRFProtect csrf = CSRFProtect() # 這塊代碼可能在文件中。 app = Flask(import_name=__name__, template_folder="templates") # 項目配置代碼之后 csrf.init_app(app) # 將插件注冊到app中去 #設(shè)置應(yīng)用程序的 secret_key,用于加密生成的 csrf_token 的值 app.config['SECRET_KEY'] = 'dafssg231bfvxvdsfwrqdqfafaffsgsbfsfsgs' @app.route("/user") def user(): title = "用戶中心" html = render_template("index12.html", **locals()) return html @app.route("/transfer", methods=["post"]) def transfer(): return "轉(zhuǎn)賬成功!" if __name__ == '__main__': app.run(debug=True)
在表單中使用 CSRF 令牌
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <form action="http://127.0.0.1:5000/transfer" method="post"> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"> 賬號:<input type="text" name="username"><br><br> 密碼:<input type="text" name="password"><br><br> <input type="submit" value="轉(zhuǎn)賬"> </form> </body> </html>
瀏覽器訪問/user頁面,表單里面會多一個隱藏的input標(biāo)簽,
當(dāng)我們點擊轉(zhuǎn)賬時,form表單中只要添加了{(lán)%csrf_token%},頁面就會自動添加個隱藏的input標(biāo)簽,每次請求得到的的value值都不相同
只要手動改下這個隱藏的input里面的value值,再提交數(shù)據(jù)就會forbidden。這個值只有是后臺給的才能通過鑒權(quán)
點擊轉(zhuǎn)賬,校驗失敗,數(shù)據(jù)提交不成功
這樣,第三方請求在提交表單時,就算猜到csrf_token的變量名,也無法猜測到服務(wù)器傳來的值,所以,就可以防范csrf攻擊
總結(jié)
簡單總結(jié)一下本文flask中CSRF攻擊的防護(hù)策略:
自動防護(hù)策略:同源檢測(Origin和Referer驗證);
主動防護(hù)策略:token驗證以及配合SameSite設(shè)置;
為了更好的防御CSRF,最佳實踐應(yīng)該是結(jié)合上面總結(jié)的防御措施方式中的優(yōu)缺點來綜合考慮,結(jié)合當(dāng)前Web應(yīng)用程序自身的情況做合適的選擇,才能更好的預(yù)防CSRF的發(fā)生。
以上就是詳解python flask是如何預(yù)防CSRF攻擊的詳細(xì)內(nèi)容,更多關(guān)于python flask預(yù)防CSRF攻擊的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
如何取消pyecharts繪制地圖時默認(rèn)顯示小圓點標(biāo)識
這篇文章主要介紹了如何取消pyecharts繪制地圖時默認(rèn)顯示小圓點標(biāo)識,文章內(nèi)容介紹詳細(xì)具有一定的參考價值?需要的小伙伴可以參考一下2022-04-04Python通過cron或schedule實現(xiàn)爬蟲的自動定時運行
自動定時運行爬蟲是很多數(shù)據(jù)采集項目的基本需求,通過 Python 實現(xiàn)定時任務(wù),可以保證數(shù)據(jù)采集的高效和持續(xù)性,本文將帶大家了解如何在 Python 中使用 cron 和 schedule 來實現(xiàn)爬蟲的自動定時運行,需要的朋友可以參考下2024-12-12matplotlib交互式數(shù)據(jù)光標(biāo)實現(xiàn)(mplcursors)
這篇文章主要介紹了matplotlib交互式數(shù)據(jù)光標(biāo)實現(xiàn)(mplcursors),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01在雙python下設(shè)置python3為默認(rèn)的方法
這篇文章主要介紹了如何在雙python下設(shè)置python3為默認(rèn),本文通過一個例子分步驟給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2018-10-10Python實現(xiàn)一個數(shù)組除以一個數(shù)的例子
今天小編就為大家分享一篇Python實現(xiàn)一個數(shù)組除以一個數(shù)的例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-07-07