Cross-site Request Forgery,常縮寫為 CSRF (或 XSRF),中文翻譯稱之為跨網站的偽造要求。除了這些稱呼,其他像是 Cross-site Reference Forgery、Session Riding、One-click Attack 等等各式各樣的名稱,其實指的都是同一種攻擊手法。 CSRF 跟 XSS (Cross-site Scripting) 都是跨網站的攻擊手法,但是 CSRF 利用的是使用者對於瀏覽器的信任而達到攻擊目的,而 XSS 則是利用使用者對於網站本身的信任。
簡單來說,CSRF 就是在使用者不知情的情況下,讓瀏覽器送出請求給目標網站以達攻擊目的。 對於 HTTP 協定有所了解的讀者,看到這句話可能會覺得很困惑。因為在預設的情況下,任何人只要知道 URL 與參數都可以對網站發出任何請求,如此說來不是所有的網站都會遭受 CSRF 的攻擊了嗎?可以說是,也可以說不是。因此嚴格來說,CSRF 通常指的是發生在使用者已經登入目標網站後,駭客利用受害者的身分來進行請求,如此一來不但可以獲得受害者的權限,而且在系統的相關紀錄中也很難發現可疑之處。
在進一步談到 CSRF 的攻擊手法之前,我要先談一下一般網站應用程式是如何識別使用者的身分。對於需要辨別使用者身分的網站而言,最常見的方法就是依靠帳號/密碼。凡使用者想要進行受限制的動作時,就必須先經過帳號/密碼的驗證。但是如果在每次進行受限制動作前都要輸入一遍帳號與密碼,我想沒有多少使用者可以忍受這樣的不便。所以所有的網站系統都會把使用者輸入且通過驗證的帳號資訊記錄下來,之後就不再進行驗證的動作了。然而因為 HTTP 協定的限制 (Stateless),所以如何紀錄這個驗證過的帳號資訊就成了棘手的問題。早期有些系統會將帳號本身紀錄在 Cookie 中,因為 Cookie 的特性就是瀏覽器在每次存取網站的同時會將內容傳回去,所以網站系統就可以從 Cookie 中獲得帳號的資訊。然而因為 Cookie 存放在使用者的電腦中,算是一個極不安全的環境,因此後來的網站系統都是在 Cookie 中存放一個隨機亂數產生的代號,網站系統再經由這個代號找出相對應的帳號資訊,這個代號我們通常稱之為 Session Token。Session Token 的概念與實作雖然很簡單,但是安全性卻依舊不足,所以為了提昇 Session 的安全性就必須採用其他補強措施。像是 Session Token 自動失效、定期更新 Session Token 的數值、加上檢查 Session Token 來源 IP 位址等方式,都可以用來增加 Session 的安全性 (主要是避免 Session Hijacking)。除了利用 Cookie 來紀錄 Session Token 外,其他像是把 Session Token 放在 URL 參數中,或是使用 Basic Authentication 的方式,雖然細節上有些不同,但是基本的原理卻都是一樣的。
偷取使用者身分比較有名 (傳統) 的手法正是前述的 Session Hijacking,CSRF 雖然跟 Session Hijacking 很類似,但是跟 Session Hijacking 不一樣的是 CSRF 並沒有真正控制整個 Session (例如取得 Session Token),而只是利用瀏覽器自動回傳使用者身分識別資訊 (如 Session Token) 的功能,讓發出的請求變成受害者的身分。所以 CSRF 利用了受害者的 Session,但是卻沒有直接進行控制,這也是為什麼 CSRF 又被稱為 Session Riding 的理由。雖然 CSRF 可以產生的破壞動作不像 Session Hijacking 那般不受限制,但是因為在 CSRF 中請求確實是由受害者的瀏覽器所發出,所以事後很難追蹤問題發生的來源,而且所有用來解決 Session Hijacking 的手法也幾乎沒有辦法避免 CSRF。此外因為進行 CSRF 攻擊時請求是由受害者的瀏覽器所發出,所以可以用來攻擊內部的 (對受害者而言) 網站系統,這點往往是 Session Hijacking 所做不到的。
CSRF 可能的攻擊情境之一可以用下列圖示加以說明:
根據 OWASP 的文件,一個 CSRF 攻擊要成功有四個要素:
- 瀏覽器處理 Cookie 與 Basic Authentication 的行為 (Web browser behavior regarding the handling of session-related information such as cookies and http authentication information)。
因為這部份是 HTTP 相關協定的規範,所以我們無法針對此點做任何防範。 - 駭客對於網址的知悉 (Knowledge by the attacker of valid web application URLs)。
如果目標網站是一個公開的系統,駭客取得 URL 資訊並不是什麼困難的事情。但是對於內部私有系統而言,駭客必須透過社交工程或其他手法取得這些資訊。 - 網站系統的 Session 管理僅依靠瀏覽器所擁有的資訊 (Application session management relying only on information which is known by the browser)。
嚴格來說,這點才是 CSRF 會造成破壞的真正元兇,而且所有的防範機制也都是針對此一要素。 - 可以觸發使用者瀏覽器發出請求的網頁元素 (Existence of HTML tags whose presence cause immediate access to an http[s] resources; for example the image tag)。
駭客可以將需要假冒的請求放到某個網頁的 image 標籤中 (也就是 <img src=”…” />),如此一來當受害者瀏覽到這個網頁後瀏覽器就會自動發出請求。因為瀏覽器在發出請求前無法判別請求的資源是否確實為圖檔,所以無論如何都會造成請求訊息的傳送 (除非使用者關閉了自動下載圖片的功能,但是我想應該沒有使用者會這樣做吧)。當然駭客也可以利用別的方式誘騙使用者按下連結,但是採用 image 標籤的方式並不需要使用者的點選就可以自動執行,所以算是最為有效的手法。
這個用來發動攻擊的網頁,通常是存放在另外一個不相干的網站系統之內。可能是受駭客控制的網站,也可能是駭客利用 XSS 等手法將假冒請求指令植入的無辜網站。如果這個無辜的網站恰巧正是目標網站本身,這種攻擊手法又稱之為 Stored CSRF,其產生的危害將更加地可怕。也就是說駭客利用 XSS 等手法將假冒的請求先植入目標網站中,因為前來瀏覽目標網站的使用者已經登入系統的可能性相對提高許多,所以 CSRF 成功的機會也隨之大幅提高。而且 Stored CSRF 因為攻擊網頁與假冒的請求屬於同一個網站,所以採用多個瀏覽器進行不同網站間瀏覽的保護方式並沒有什麼作用。事實上, Stored CSRF 對使用者而言幾乎是沒有什麼方法可以加以避免的。
除了可以使用 XSS 手法植入假冒的請求外,如果網站系統允許使用者透過 URL 連結外部圖檔但是卻沒有檢查連結資源是否確實為圖檔,也很可能遭受這樣的攻擊。也就是說像 Web Mail 這類可以接受內嵌外部圖檔的訊息網站,很容易成為駭客用來發動 CSRF 的平台。
對 CSRF 有所了解後,在下一篇的文章中我們來談談如何避免 CSRF 的危害。