理解CSRF(跨站請求偽造)
對於Express團隊的csrf模組和csurf模組的加密函式的用法我們經常有一些在意。
這些在意是莫須有的,因為他們不瞭解CSRF token是如何工作的。 下面快速過一遍!
讀過後還有疑問?希望告訴我們錯誤?請開一個issue!
一個CSRF攻擊是如何工作的?
在他們的釣魚站點,攻擊者可以通過建立一個AJAX按鈕或者表單來針對你的網站建立一個請求:
<form action="https://my.site.com/me/something-destructive" method="POST">
<button type="submit">Click here for free money!</button>
</form>
這是很危險的,因為攻擊者可以使用其他http方法例如 delete
來獲取結果。 這在使用者的session中有很多關於你的網站的詳細資訊時是相當危險的。 如果一個不懂技術的使用者遇到了,他們就有可能會輸入信用卡號或者個人安全資訊。
如果減輕CSRF攻擊?
只使用JSON
api
使用JavaScript發起AJAX請求是限制跨域的。 不能通過一個簡單的<form>
來傳送JSON
,
所以,通過只接收JSON,你可以降低發生上面那種情況的可能性。
禁用CORS
第一種減輕CSRF攻擊的方法是禁用cross-origin requests(跨域請求)。 如果你希望允許跨域請求,那麼請只允許 OPTIONS, HEAD, GET
方法,因為他們沒有副作用。
不幸的是,這不會阻止上面的請求由於它沒有使用JavaScript(因此CORS不適用)。
檢驗referrer頭部
不幸的是,檢驗referrer頭部很麻煩, 但是你可以阻止那些referrer頭部不是來自你的頁面的請求。 這實在不值得麻煩。
舉個例子,你不能載入session如果這個請求的referrer頭部不是你的伺服器。
GET總是冪等的
確保你的GET
請求不會修改你資料庫中的相關資料。 這是一個初學者常犯的錯誤,使得你的應用不僅是易於遭受CSRF攻擊。
避免使用POST
因為<form>
只能用GET
或是POST
,
而不能使用別的方法,例如PUT
, PATCH
, DELETE
,
攻擊者很難有方法攻擊你的網站。
不要複寫方法
許多應用程式使用複寫方法來在一個常規表單中使用PUT
, PATCH
,
和DELETE
請求。 這會使得原先不易受攻擊的方法變得易受攻擊。
不要相容舊瀏覽器
舊的瀏覽器不支援CORS或是其他安全政策。 通過不相容舊瀏覽器 (那些不懂技術的人用的越多,我們越容易被攻擊), 你可以最小化受到攻擊的可能性。
CSRF
Tokens
最終的解決辦法是使用CSRF tokens。 CSRF tokens是如何工作的呢?
- 伺服器傳送給客戶端一個token。
- 客戶端提交的表單中帶著這個token。
- 如果這個token不合法,那麼伺服器拒絕這個請求。
攻擊者需要通過某種手段獲取你站點的CSRF token, 他們只能使用JavaScript來做。 所以,如果你的站點不支援CORS, 那麼他們就沒有辦法來獲取CSRF token, 降低了威脅。
確保CSRF token不能通過AJAX訪問到! 不要建立一個/CSRF
路由來獲取一個token, 尤其不要在這個路由上支援CORS!
token需要是不容易被猜到的, 讓它很難被攻擊者嘗試幾次得到。 它不需要是密碼安全的。 攻擊來自從一個未知的使用者的一次或者兩次的點選, 而不是來自一臺伺服器的暴力攻擊。
BREACH攻擊
這也就是salt(加鹽)出現的原因。 Breach攻擊相當簡單:如果伺服器通過HTTPS+gzip
多次傳送相同或者相似的響應,攻擊者就可以猜測響應的內容(使得HTTPS完全無用)。 解決辦法?讓每一個響應都有那麼一點不同。 於是,CSRF tokens依據每一個不同的請求還有不同的時間來生成。
但是伺服器需要知道客戶端請求中帶的token是否是合法的。 因此:
- 一般認為安全加密的CSRF tokens是防護CSRF的關鍵
- CSRF tokens現在通常是一個祕鑰或者salt的hash
瞭解更多:
注意,CSRF沒有_解決_BREACH攻擊, 但是這個模組通過隨機化請求來為你減輕BREACH攻擊。
salt不需要加密
因為客戶端知道salt!!! 伺服器會傳送 <salt>;<token>
,然後客戶端會通過請求返回相同的值給伺服器。伺服器然後會檢驗<secret>+<salt>=<token>
。
salt必須跟token一起被髮送給伺服器,否則伺服器不能驗證這個token。 這是最簡單的加密方式。 還有很多方法,不過他們更加複雜,犯不著那麼麻煩。
建立tokens必須要快
因為每當進來一個請求他們就會被建立! 像Math.random().toString(36).slice(2)
這麼做也是效能足夠好的! 你不需要OpenSSL來為每一個請求建立一個密碼安全的token。
祕鑰不需要是加密的,但需要是安全的
如果你正在使用一個資料庫後端來儲存session,客戶端是不會知道祕鑰的,因為它被儲存在資料庫中。 如果你正在使用cookie來儲存session,那麼祕鑰就會被儲存在cookie中傳送給客戶端。 因此, 確保cookie sessions 使用 httpOnly
那樣客戶端就不能通過客戶端JavaScript來讀取到祕鑰!
當你不正確的使用CSRF
token
把它們加到JSON
AJAX呼叫中
正如上面提到的,如果你不支援CORS並且你的API是傳輸的嚴格的JSON, 絕沒可能在你的AJAX 呼叫中加入CSRF token。
通過AJAX暴露你的CSRF
token
不要建立一個GET /csrf
路由 並且尤其不要在這個路由上支援CORS。 不要傳送CSRF token在API響應的body中。
結論
因為web正在向JSON API轉移,並且瀏覽器變得更安全,有更多的安全策略, CSRF正在變得不那麼值得關注。 阻止舊的瀏覽器訪問你的站點,並儘可能的將你的API變成JSON API, 然後你將不再需要CSRF token。 但是為了安全起見,你還是應該儘量允許他們尤其是當難以實現的時候。
相關文章
- CSRF - 跨站請求偽造
- 跨站請求偽造CSRF攻防
- [Http] 跨站請求偽造(CSRF)HTTP
- CSRF(跨站請求偽造)簡介
- CSRF跨站請求偽造漏洞分析
- 跨站請求偽造(CSRF)-簡述
- l初識CSRF(跨站請求偽造)
- CSRF 跨站請求偽造學習筆記筆記
- SpringSecurity原理解析以及CSRF跨站請求偽造攻擊SpringGse
- 密碼學系列之:csrf跨站點請求偽造密碼學
- 跨站請求偽造(CSRF)攻擊原理及預防手段
- Django csrf跨站請求偽造,校驗,CBV忽略與允許csrf校驗Django
- Django中如何防範CSRF跨站點請求偽造攻擊Django
- [譯] 跨站請求偽造已死!
- 08 CSRF偽造請求攻擊
- Django框架:13、csrf跨站請求偽造、auth認證模組及相關用法Django框架
- Django框架之csrf跨站請求Django框架
- 什麼是CSRF跨站請求偽造?(from表單效驗csrf-ajdax效驗csrf-Ajax設定csrf-CBV裝飾器驗證csrf)
- csrf解決Ajax請求跨站問題
- DVWA學習記錄系列(四)SCRF 跨站偽造請求模組CRF
- jenkins v2.229 版本,無法勾選 “跨站請求偽造保護”Jenkins
- Django CBV裝飾器 中介軟體 auth模組 CSRF跨站請求Django
- Anchor CMS 0.12.7 跨站請求偽造漏洞(CVE-2020-23342)
- SSRF 服務端請求偽造服務端
- java 偽造http請求ip地址JavaHTTP
- php模擬請求(偽造來源和請求ip)PHP
- .NET Core實戰專案之CMS 第十四章 開發篇-防止跨站請求偽造
- 伺服器端請求偽造(SSRF)簡介伺服器
- 跨域請求跨域
- 偽造工作經歷,請止步!!!
- CORS跨域請求CORS跨域
- vue跨域請求Vue跨域
- .net core 一個避免跨站請求的中介軟體
- AJAX 跨源 HTTP 請求HTTP
- jquery ajax 跨域請求jQuery跨域
- 允許跨域請求跨域
- 跨域ajax請求,伺服器會收到請求嗎?跨域伺服器
- 同源政策與跨域請求跨域