原文出處Understanding CSRFhtml
對於Express團隊的csrf模塊和csurf模塊的加密函數的用法咱們常常有一些在乎。 這些在乎是莫須有的,由於他們不瞭解CSRF token是如何工做的。 下面快速過一遍!git
讀事後還有疑問?但願告訴咱們錯誤?請開一個issue!github
在他們的釣魚站點,攻擊者能夠經過建立一個AJAX按鈕或者表單來針對你的網站建立一個請求:web
<form action="https://my.site.com/me/something-destructive" method="POST">
<button type="submit">Click here for free money!</button>
</form>
這是很危險的,由於攻擊者可使用其餘http方法例如 delete
來獲取結果。 這在用戶的session中有不少關於你的網站的詳細信息時是至關危險的。 若是一個不懂技術的用戶遇到了,他們就有可能會輸入信用卡號或者我的安全信息。ajax
使用JavaScript發起AJAX請求是限制跨域的。 不能經過一個簡單的<form>
來發送JSON
, 因此,經過只接收JSON,你能夠下降發生上面那種狀況的可能性。數據庫
第一種減輕CSRF攻擊的方法是禁用cross-origin requests(跨域請求)。 若是你但願容許跨域請求,那麼請只容許 OPTIONS, HEAD, GET
方法,由於他們沒有反作用。express
不幸的是,這不會阻止上面的請求因爲它沒有使用JavaScript(所以CORS不適用)。json
不幸的是,檢驗referrer頭部很麻煩, 可是你能夠阻止那些referrer頭部不是來自你的頁面的請求。 這實在不值得麻煩。後端
舉個例子,你不能加載session若是這個請求的referrer頭部不是你的服務器。api
確保你的GET
請求不會修改你數據庫中的相關數據。 這是一個初學者常犯的錯誤,使得你的應用不只是易於遭受CSRF攻擊。
由於<form>
只能用GET
或是POST
, 而不能使用別的方法,例如PUT
, PATCH
, DELETE
, 攻擊者很難有方法攻擊你的網站。
許多應用程序使用複寫方法來在一個常規表單中使用PUT
, PATCH
, 和DELETE
請求。 這會使得原先不易受攻擊的方法變得易受攻擊。
舊的瀏覽器不支持CORS或是其餘安全政策。 經過不兼容舊瀏覽器 (那些不懂技術的人用的越多,咱們越容易被攻擊), 你能夠最小化受到攻擊的可能性。
最終的解決辦法是使用CSRF tokens。 CSRF tokens是如何工做的呢?
攻擊者須要經過某種手段獲取你站點的CSRF token, 他們只能使用JavaScript來作。 因此,若是你的站點不支持CORS, 那麼他們就沒有辦法來獲取CSRF token, 下降了威脅。
確保CSRF token不能經過AJAX訪問到! 不要建立一個/CSRF
路由來獲取一個token, 尤爲不要在這個路由上支持CORS!
token須要是不容易被猜到的, 讓它很難被攻擊者嘗試幾回獲得。 它不須要是密碼安全的。 攻擊來自從一個未知的用戶的一次或者兩次的點擊, 而不是來自一臺服務器的暴力攻擊。
這也就是salt(加鹽)出現的緣由。 Breach攻擊至關簡單:若是服務器經過HTTPS+gzip
屢次發送相同或者類似的響應,攻擊者就能夠猜想響應的內容(使得HTTPS徹底無用)。 解決辦法?讓每個響應都有那麼一點不一樣。 因而,CSRF tokens依據每個不一樣的請求還有不一樣的時間來生成。 可是服務器須要知道客戶端請求中帶的token是不是合法的。 所以:
瞭解更多:
注意,CSRF沒有_解決_BREACH攻擊, 可是這個模塊經過隨機化請求來爲你減輕BREACH攻擊。
由於客戶端知道salt!!! 服務器會發送 <salt>;<token>
,而後客戶端會經過請求返回相同的值給服務器。服務器而後會檢驗 <secret>+<salt>=<token>
。 salt必須跟token一塊兒被髮送給服務器,不然服務器不能驗證這個token。 這是最簡單的加密方式。 還有不少方法,不過他們更加複雜,犯不着那麼麻煩。
由於每當進來一個請求他們就會被建立! 像Math.random().toString(36).slice(2)
這麼作也是性能足夠好的! 你不須要OpenSSL來爲每個請求建立一個密碼安全的token。
若是你正在使用一個數據庫後端來存儲session,客戶端是不會知道祕鑰的,由於它被存儲在數據庫中。 若是你正在使用cookie來存儲session,那麼祕鑰就會被存儲在cookie中發送給客戶端。 所以, 確保cookie sessions 使用 httpOnly
那樣客戶端就不能經過客戶端JavaScript來讀取到祕鑰!
正如上面提到的,若是你不支持CORS而且你的API是傳輸的嚴格的JSON, 絕沒可能在你的AJAX 調用中加入CSRF token。
不要建立一個GET /csrf
路由 而且尤爲不要在這個路由上支持CORS。 不要發送CSRF token在API響應的body中。
由於web正在向JSON API轉移,而且瀏覽器變得更安全,有更多的安全策略, CSRF正在變得不那麼值得關注。 阻止舊的瀏覽器訪問你的站點,並儘量的將你的API變成JSON API, 而後你將再也不須要CSRF token。 可是爲了安全起見,你仍是應該儘可能容許他們尤爲是當難以實現的時候。