還記得我們在前面表單的原始碼出現的{% csrf_token %}
嗎? 今天會來稍微介紹它是用來做什麼的? 沒有它會發生什麼?它解決了什麼問題?
它的全名是Cross Site Request Forgery
,中文名稱是跨站請求偽造
,是一種常見的網路攻擊手段。該攻擊手段利用的是使用者對於瀏覽器的信任,使用者登入網路應用程式通常採用cookie
或session
作為身分驗證,而瀏覽器則將這些身分驗證資訊存起來一段時間,保證在這段時間內,使用者可以輕鬆使用網路應用程式的各項功能而無須再驗證身分。
這樣聽起來還挺不錯的吧! 那問題又是出在哪呢?
前面有說過CSRF
攻擊能成功靠的是使用者對於瀏覽器的信任,因為身分驗證資訊被瀏覽器記住,所以也就代表瀏覽器後續發出的各種請求都代表使用者本人
,這就產生很大的問題,即存在瀏覽器在非使用者自願的情況下,在其他網站對網路應用程式發出請求的可能性。(網路應用程式只認瀏覽器有的身分資訊,它不過問使用者意願)
舉一個簡單的CSRF
攻擊例子 :
假設網站刪除使用者資料操作的URL
位址是https://demo.example.com/members/delete/1
。
那想透過CSRF
手段進行攻擊的人可以怎麼做?
相對簡單的作法是在另一個使用者會進入的網站嵌入這段原始碼: <img src="https://demo.example.com/members/delete/1" />
。
如果使用者剛好存取到這個惡意網站,而且他的身分驗證資訊又放在瀏覽器還沒過期,那麼他回過頭來就會發現自己在網站上有筆資料不見了。
(圖片來源)
透過 CSRF 發動攻擊的人不需要竊取使用者的個人資訊,只要利用使用者對瀏覽器使用感到方便的心態,默默等待機會去誘發瀏覽器發出對特定 URL 位址的請求即可。後面的 CSRF Token 算是應 CSRF 攻擊而生的其中一種預防方法。
CSRF Token
的簡單概念是既然不知道發出請求的是不是攻擊者,那試著產生1個只有使用者在同網站送出請求才會有的序號,而當攻擊者想在其他網站藉由嵌入原始碼送出刪除資料的請求,此時送出的請求並不會有這組序號,這樣就可以很輕鬆的認出誰是攻擊者。
CSRF Token
實際在Django
表單應用的例子:
在表單裡面插入{% csrf_token %}
{% csrf_token %}
會產生一組隱藏欄位也就是CSRF Token
提交表單所產生的request
會連同這組CSRF Token
被送出去,而Django
應用程式要做的就是確認這組CSRF Token
的存在,去驗證修改資料的請求是否來自同個網站。
但這樣就沒問題了嗎? 當然有問題。
有一種攻擊手段叫做中間人攻擊(Man-in-the-middle attack,MITM),該攻擊手段試著從中間插入使用者傳送request
到後端 Server 的聯絡管道,當使用者確認資料無誤,將資料送出到 Server,攻擊者可以在這個過程中,試著攔截使用者送出的request
,如果成功攔截,就會導致CSRF Token
的外流,讓它失去原本的作用,而要怎麼預防攔截就又是另一個故事了。
(圖片來源)
番外篇到此結束。明天會接續Day 15的內容,往下介紹如何在網頁上刪除資料表的紀錄(Record)。