使用 Golang 打造 Web 應用程式
  • Introduction
  • Go 環境配置
    • Go 安裝
    • GOPATH 與工作空間
    • Go 命令
    • Go 開發工具
    • 小結
  • Go 語言基礎
    • 你好,Go
    • Go 基礎
    • 流程和函式
    • struct
    • 物件導向
    • interface
    • 併發
    • 小結
  • Web 基礎
    • web 工作方式
    • Go 建立一個簡單的 web 服務
    • Go 如何使得 web 工作
    • Go 的 http 套件詳解
    • 小結
  • 表單
    • 處理表單的輸入
    • 驗證表單的輸入
    • 預防跨站指令碼
    • 防止多次提交表單
    • 處理檔案上傳
    • 小結
  • 存取資料庫
    • database/sql 介面
    • 使用 MySQL 資料庫
    • 使用 SQLite 資料庫
    • 使用 PostgreSQL 資料庫
    • 使用 beedb 函式庫進行 ORM 開發
    • NoSQL 資料庫操作
    • 小結
  • session 和資料儲存
    • session 和 cookie
    • Go 如何使用 session
    • session 儲存
    • 預防 session 劫持
    • 小結
  • 文字檔案處理
    • XML 處理
    • JSON 處理
    • 正則處理
    • 範本處理
    • 檔案操作
    • 字串處理
    • 小結
  • Web 服務
    • Socket 程式設計
    • WebSocket
    • REST
    • RPC
    • 小結
  • 安全與加密
    • 預防 CSRF 攻擊
    • 確保輸入過濾
    • 避免 XSS 攻擊
    • 避免 SQL 注入
    • 儲存密碼
    • 加密和解密資料
    • 小結
  • 國際化和本地化
    • 設定預設地區
    • 本地化資源
    • 國際化站點
    • 小結
  • 錯誤處理,除錯和測試
    • 錯誤處理
    • 使用 GDB 除錯
    • Go 怎麼寫測試案例
    • 小結
  • 部署與維護
    • 應用日誌
    • 網站錯誤處理
    • 應用部署
    • 備份和還原
    • 小結
  • 如何設計一個 Web 框架
    • 專案規劃
    • 自訂路由器設計
    • controller 設計
    • 日誌和配置設計
    • 實現部落格的增刪改
    • 小結
  • 擴充套件 Web 框架
    • 靜態檔案支援
    • Session 支援
    • 表單支援
    • 使用者認證
    • 多語言支援
    • pprof 支援
    • 小結
  • 參考資料
Powered by GitBook
On this page
  • 什麼是 CSRF
  • CSRF 的原理
  • 如何預防 CSRF
  • 總結
  • links

Was this helpful?

  1. 安全與加密

預防 CSRF 攻擊

Previous安全與加密Next確保輸入過濾

Last updated 4 years ago

Was this helpful?

什麼是 CSRF

CSRF(Cross-site request forgery),中文名稱:跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF。

那麼 CSRF 到底能夠幹嘛呢?你可以這樣簡單的理解:攻擊者可以盜用你的登陸資訊,以你的身份模擬傳送各種請求。攻擊者只要藉助少許的社會工程學的詭計,例如透過 QQ 等聊天軟體傳送的連結(有些還偽裝成短域名,使用者無法分辨),攻擊者就能迫使 Web 應用的使用者去執行攻擊者預設的操作。例如,當用戶登入網路銀行去檢視其存款餘額,在他沒有退出時,就點選了一個 QQ 好友發來的連結,那麼該使用者銀行帳戶中的資金就有可能被轉移到攻擊者指定的帳戶中。

所以遇到 CSRF 攻擊時,將對終端使用者的資料和操作指令構成嚴重的威脅;當受攻擊的終端使用者具有管理員帳戶的時候,CSRF 攻擊將危及整個 Web 應用程式。

CSRF 的原理

下圖簡單闡述了 CSRF 攻擊的思想

圖 9.1 CSRF 的攻擊過程

從上圖可以看出,要完成一次 CSRF 攻擊,受害者必須依次完成兩個步驟 :

  • 1.登入受信任網站 A,並在本地產生 Cookie 。

  • 2.在不退出 A 的情況下,存取危險網站 B。

看到這裡,讀者也許會問:“如果我不滿足以上兩個條件中的任意一個,就不會受到 CSRF 的攻擊”。是的,確實如此,但你不能保證以下情況不會發生:

  • 你不能保證你登入了一個網站後,不再開啟一個 tab 頁面並存取另外的網站,特別現在瀏覽器都是支援多 tab 的。

  • 你不能保證你關閉瀏覽器了後,你本地的 Cookie 立刻過期,你上次的會話已經結束。

  • 上圖中所謂的攻擊網站,可能是一個存在其他漏洞的可信任的經常被人存取的網站。

因此對於使用者來說很難避免在登陸一個網站之後不點選一些連結進行其他操作,所以隨時可能成為 CSRF 的受害者。

CSRF 攻擊主要是因為 Web 的隱式身份驗證機制,Web 的身份驗證機制雖然可以保證一個請求是來自於某個使用者的瀏覽器,但卻無法保證該請求是使用者批准傳送的。

如何預防 CSRF

過上面的介紹,讀者是否覺得這種攻擊很恐怖,意識到恐怖是個好事情,這樣會促使你接著往下看如何改進和防止類似的漏洞出現。

CSRF 的防禦可以從伺服器端和客戶端兩方面著手,防禦效果是從伺服器端著手效果比較好,現在一般的 CSRF 防禦也都在伺服器端進行。

伺服器端的預防 CSRF 攻擊的方式方法有多種,但思想上都是差不多的,主要從以下 2 個方面入手:

  • 1、正確使用 GET,POST 和 Cookie;

  • 2、在非 GET 請求中增加偽隨機數;

我們上一章介紹過 REST 方式的 Web 應用,一般而言,普通的 Web 應用都是以 GET、POST 為主,還有一種請求是 Cookie 方式。我們一般都是按照如下方式設計應用:

1、GET 常用在檢視,列舉,展示等不需要改變資源屬性的時候;

2、POST 常用在下達訂單,改變一個資源的屬性或者做其他一些事情;

接下來我就以 Go 語言來舉例說明,如何限制對資源的存取方法:

mux.Get("/user/:uid", getuser)
mux.Post("/user/:uid", modifyuser)

這樣處理後,因為我們限定了修改只能使用 POST,當 GET 方式請求時就拒絕回應,所以上面圖示中 GET 方式的 CSRF 攻擊就可以防止了,但這樣就能全部解決問題了嗎?當然不是,因為 POST 也是可以模擬的。

因此我們需要實施第二步,在非 GET 方式的請求中增加隨機數,這個大概有三種方式來進行:

  • 為每個使用者產生一個唯一的 cookie token,所有表單都包含同一個偽隨機值,這種方案最簡單,因為攻擊者不能獲得第三方的 Cookie(理論上),所以表單中的資料也就構造失敗,但是由於使用者的 Cookie 很容易由於網站的 XSS 漏洞而被盜取,所以這個方案必須要在沒有 XSS 的情況下才安全。

  • 每個請求使用驗證碼,這個方案是完美的,因為要多次輸入驗證碼,所以使用者友好性很差,所以不適合實際運用。

  • 不同的表單包含一個不同的偽隨機值,我們在 4.4 小節介紹“如何防止表單多次提交”時介紹過此方案,複用相關程式碼,實現如下:

產生隨機數 token

h := md5.New()
io.WriteString(h, strconv.FormatInt(crutime, 10))
io.WriteString(h, "ganraomaxxxxxxxxx")
token := fmt.Sprintf("%x", h.Sum(nil))

t, _ := template.ParseFiles("login.gtpl")
t.Execute(w, token)

輸出 token

<input type="hidden" name="token" value="{{.}}">

驗證 token

r.ParseForm()
token := r.Form.Get("token")
if token != "" {
    //驗證 token 的合法性
} else {
    //不存在 token 報錯
}

這樣基本就實現了安全的 POST,但是也許你會說如果破解了 token 的演算法呢,按照理論上是,但是實際上破解是基本不可能的,因為有人曾計算過,暴力破解該串大概需要 2 的 11 次方時間。

總結

跨站請求偽造,即 CSRF,是一種非常危險的 Web 安全威脅,它被 Web 安全界稱為“沉睡的巨人”,其威脅程度由此“美譽”便可見一斑。本小節不僅對跨站請求偽造本身進行了簡單介紹,還詳細說明造成這種漏洞的原因所在,然後以此提了一些防範該攻擊的建議,希望對讀者編寫安全的 Web 應用能夠有所啟發。

links

上一節:

下一節:

目錄
安全與加密
確保輸入過濾