Web 安全防護戰 - 淺談CSRF

文章首發於 Web 安全防護戰 - 淺談CSRFphp

在進入 web 安全知識以前,建議對 HTTP 有所瞭解,能夠看HTTP 入門體檢,會對如下的內容有所幫助。html

CSRF(Cross-site request forgery)

CSRF,跨站請求僞造。也被稱爲one-click attack或者session riding,一般縮寫爲CSRF或者XSRF。是一種挾制用戶在當前已登陸的Web應用程序上執行非本意的操做的攻擊方法。前端

XSS(Cross Site) 和 CSRF(Cross Site) 區別

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>" />
複製代碼

大概的流程以下:後端

  • 在 CSRF 網站,向博客網站發起了攻擊評論CSRF 攻擊(GET請求);
  • 而後在博客網站就會發現了一條 匿名信息:CSRF 攻擊 的評論;
  • 假如該 CSRF攻擊 評論是~超連接~,那麼用戶點擊了就會觸發攻擊,或者是自行運行的腳本,用戶只要打開這個頁面就會觸發攻擊;

CSRF 攻擊原理

  • 用戶登陸存在漏洞的健康網站A;
  • 網站A 服務器驗證了用戶的身份以後,響應該用戶的 Cookie 做爲身份憑證;
  • 攻擊網站B 檢查到網站A 的漏洞或者引誘用戶在 A網站 訪問 B網站,這樣攻擊網站就能夠帶上用戶的身份憑證向 網站A 發起請求(攻擊);

常見危害

  • 利用用戶登陸態盜取用戶資金;
  • 在用戶不知情的狀況下冒充用戶作違法亂紀的事情;
  • 私自完成業務請求,致使損壞網站名譽;
  • …..

常見防護方法

Set-Cookie: SameSite

禁止第三方網站帶 Cookies,即在響應頭 Set-Cookie 設置 SameSite 屬性,表示該 Cookie 問同源網站而非來源第三方網站。如 Koa2 設置以下:api

ctx.cookies.set([cookie_key], [cookie_value], {sameSite: 'strict' | 'lax'};
複製代碼

其中 strictlax 區別以下:跨域

// B網站 API 響應頭設置以下:
Set-Cookie: foo=1; Samesite=Strict
Set-Cookie: bar=2; Samesite=Lax
Set-Cookie: baz=3
複製代碼
  1. 假如在 A網站 請求 B網站 的 API,那麼 foo=1 這個 Cookie 是不會從 A網站 帶到 B網站的;
  2. Lax,只會在使用危險 HTTP 方法時發送跨域 Cookie 被阻止,如 POST 請求。假如 A 網站 有一個超連接 GET 請求 B網站的 API,那麼這時候 Cookie 是能夠從 A網站 帶到 B網站的;
  3. baz=3 是能夠從 A網站 帶到 B網站;

注意:

Lax 的防範有限,而 Strict 則一棒子打死,因此先對大多數 Cookie 設置爲 Lax 做爲 CSRF 攻擊緩解措施,而針對某部分認爲存在危險可能的 Cookie才設置 Strict。另外,SameSite Cookie 在子域不支持共享,也就是說父域登陸後在子域還須要從新登陸,這顯然不夠友好,並且還存在兼容性問題。

驗證碼校驗 或 CSRF Token

不管是驗證碼仍是 CSRF Token,道理都是同樣的,就是爲了保證只有在本網站才能得到到的隨機驗證碼

驗證碼的原理:

  • 用戶在請求的地方,會去請求服務器申請一個驗證碼,通常來講是圖片;
  • 服務器收到請求後,會隨機生成驗證碼captcha,隨後將其文本值以及對應的用戶信息緩存下來,而且將圖片二進制信息響應回去;
  • 用戶獲得圖片驗證碼以後,將其文本信息跟隨者請求一塊兒帶過去給服務器;
  • 服務器隨後根據用戶信息取出對應的驗證碼而且進行校驗。

驗證碼實現雖然簡單,可是咱們不能讓用戶請求的時候都提交驗證碼,這樣會影響用戶體驗。

CSRF Token的原理:

  • 服務器須要生成一個經過加密算法加密的 Token;
  • 將該 Token 保存至Cookie,更安全高效的是應該保存在 Session 或者 Redis;
  • 將該 Token 傳給客戶端,客戶端在請求時要將其 Token 一併帶上,如 GET 請求 /api/message?token=xxxPOST 請求在form表單追加 <input type="hidden" name="token" value="xxx"/>Ajax 請求在頁面添加<meta name="csrf" content="token" />,經過 JS 去獲取該 meta 值;
  • 請求到服務器後,服務器就能夠經過解密對比來判斷該 Token 的有效性了。

注:

Token 雖然頗有效的防護 CSRF,可是實現複雜,不只須要前端這邊的請求都帶上 Token,並且後端也須要對每一個接口都進行校驗,所以工做量比較大。

同源策略

OriginReferer,都是用來表示請求源地址。在大多數場景中,會跟隨着請求頭髮送到服務器,而後服務器經過解析頭部值,獲取請求來源地址。通常來講,咱們在服務器設置好容許請求地址經過的白名單,而後當服務器拿到請求的來源地址,就能夠進行過濾了。

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」 />
  • 特定元素隱藏:aarealinkiframeimg 能夠經過 referrerPolicy 進行設置隱藏 referrerPolicy="never"referrerPolicy="no-referrer"。其中 alink 還能夠經過設置rel="noreferrer"
  • 低版本IE(六、7)隱藏:window.location.href=urlwindow.open 時會丟失Referer

總的來講,CSRF 危害很大,並且還跟 XSS 同樣很難防範。雖說咱們在上面羅列的接種防護策略能夠很大程度上防護 CSRF 攻擊,可是並不是十全十美。因此咱們只有根據本身的實際狀況來選擇最合適的策略,這樣才能下降受到 CSRF 攻擊的機率。哦,對了,在防護 CSRF 以前,須要先防護 XSS

參考

相關文章
相關標籤/搜索