文章首發於 Web 安全防護戰 - 淺談CSRF。php
在進入 web 安全知識以前,建議對 HTTP 有所瞭解,能夠看HTTP 入門體檢,會對如下的內容有所幫助。html
CSRF,跨站請求僞造。也被稱爲one-click attack或者session riding,一般縮寫爲CSRF或者XSRF。是一種挾制用戶在當前已登陸的Web應用程序上執行非本意的操做的攻擊方法。前端
XSS 的 Cross Site主要是指在本網站運行了來自其餘網站的腳本,而 CSRF 的Cross Site則相反,指在其餘網站對本網站形成了影響。跟 XSS 相比,XSS 利用的是用戶對指定網站的信任,CSRF 利用的是網站對用戶網頁瀏覽器的信任。git
咱們在本地搭建兩個破爛的網站,一個模擬 CSRF 攻擊網站,另外一個模擬博客網站。咱們的博客網站是採起 GET
方法來發送評論(偷懶,不要模仿)。github
匿名信息的狀況下:web
// 攻擊網站攻擊代碼
<img src="http://localhost:3000/?message=CSRF 攻擊" />
複製代碼
誘引用戶點擊進行CSRF攻擊的狀況以下:算法
// 攻擊網站攻擊代碼
<img src="http://localhost:3000/?message=<a href=http://www.csrf.com/>點了會有好事發生!</a>" />
複製代碼
大概的流程以下:後端
GET
請求);禁止第三方網站帶 Cookies,即在響應頭 Set-Cookie
設置 SameSite 屬性,表示該 Cookie 問同源網站而非來源第三方網站。如 Koa2 設置以下:api
ctx.cookies.set([cookie_key], [cookie_value], {sameSite: 'strict' | 'lax'};
複製代碼
其中 strict
與 lax
區別以下:跨域
// B網站 API 響應頭設置以下:
Set-Cookie: foo=1; Samesite=Strict
Set-Cookie: bar=2; Samesite=Lax
Set-Cookie: baz=3
複製代碼
foo=1
這個 Cookie 是不會從 A網站 帶到 B網站的;Lax
,只會在使用危險 HTTP 方法時發送跨域 Cookie 被阻止,如 POST 請求。假如 A 網站 有一個超連接 GET 請求 B網站的 API,那麼這時候 Cookie 是能夠從 A網站 帶到 B網站的;baz=3
是能夠從 A網站 帶到 B網站;注意:
Lax 的防範有限,而 Strict 則一棒子打死,因此先對大多數 Cookie 設置爲 Lax 做爲 CSRF 攻擊緩解措施,而針對某部分認爲存在危險可能的 Cookie才設置 Strict。另外,SameSite Cookie 在子域不支持共享,也就是說父域登陸後在子域還須要從新登陸,這顯然不夠友好,並且還存在兼容性問題。
不管是驗證碼仍是 CSRF Token,道理都是同樣的,就是爲了保證只有在本網站才能得到到的隨機驗證碼。
驗證碼的原理:
驗證碼實現雖然簡單,可是咱們不能讓用戶請求的時候都提交驗證碼,這樣會影響用戶體驗。
CSRF Token的原理:
GET
請求 /api/message?token=xxx
或 POST
請求在form表單追加 <input type="hidden" name="token" value="xxx"/>
或 Ajax
請求在頁面添加<meta name="csrf" content="token" />
,經過 JS 去獲取該 meta 值;注:
Token 雖然頗有效的防護 CSRF,可是實現複雜,不只須要前端這邊的請求都帶上 Token,並且後端也須要對每一個接口都進行校驗,所以工做量比較大。
Origin
、Referer
,都是用來表示請求源地址。在大多數場景中,會跟隨着請求頭髮送到服務器,而後服務器經過解析頭部值,獲取請求來源地址。通常來講,咱們在服務器設置好容許請求地址經過的白名單,而後當服務器拿到請求的來源地址,就能夠進行過濾了。
Origin 說到 Origin
,就不得不提 CORS 了。CORS 須要瀏覽器和服務器同時支持。目前,全部瀏覽器都支持該功能,~IE 瀏覽器不能低於IE10~。一旦請求發生 CORS,那麼請求頭部信息就會攜帶 Origin
,可是假如發生302重定向,那麼Origin也不會跟隨着請求頭部信息一塊兒發送給服務器。
Referer Referer
的值是由瀏覽器提供的,每一次的 HTTP 請求首部中都會有該字段,不論是Ajax請求,仍是圖片。既然由瀏覽器提供,那麼就存在被攻擊者刻意隱藏,甚至僞造Referer
的值。
控制Referer
的策略以下:
舊策略屬性值 | 新策略屬性值 |
---|---|
never | no-referrer |
default | no-referrer-when-downgrade |
always | unsafe-url |
origin-when-crossorigin | origin-when-cross-origin |
經過設置 HTTP 響應頭 Content-Security-Policy
來指定 Referrer
策略:Content-Security-Policy: referrer no-referrer|no-referrer-when-downgrade|unsafe-url|origin-when-cross-origin;
策略屬性值說明:
no-referrer
:任何狀況都不發送 Referer
;no-referrer-when-downgrade
:當協議發生降級(如 HTTPS 頁面跳轉/引入 HTTP 頁面)時不發送Referer
;unsafe-url
:不安全策略,不管什麼狀況都發送Referer
;origin-when-crossorigin
:盡在發生跨域以及包含host的前提下發送Referer
。隱藏Referer
有如下幾種狀況:
<meta name=「referrer」 content=「never」 />
或 <meta name=「referrer」 content=「no-referrer」 />
;a
、area
、link
、iframe
和 img
能夠經過 referrerPolicy
進行設置隱藏 referrerPolicy="never"
或 referrerPolicy="no-referrer"
。其中 a
和 link
還能夠經過設置rel="noreferrer"
;window.location.href=url
或 window.open
時會丟失Referer
。總的來講,CSRF 危害很大,並且還跟 XSS 同樣很難防範。雖說咱們在上面羅列的接種防護策略能夠很大程度上防護 CSRF 攻擊,可是並不是十全十美。因此咱們只有根據本身的實際狀況來選擇最合適的策略,這樣才能下降受到 CSRF 攻擊的機率。哦,對了,在防護 CSRF 以前,須要先防護 XSS。