在前面我們說過,很多時候大部分的系統漏洞都是很難發現的,這時候大部分的黑客就會通過偽造網站,從而變相獲取我們的數據。這其中涉及的方式便是CSRF攻擊。
CSRF全稱Cross Site Request Forgery,即跨站點請求偽造。我們知道,攻擊時常常伴隨著各種各樣的請求,而攻擊的發生也是由各種請求造成的。
從前面這個名字里我們可以關注到兩個點:一個是“跨站點”,另一個是“偽造”。前者說明了CSRF攻擊發生時所伴隨的請求的來源,后者說明了該請求的產生方式。所謂偽造即該請求并不是用戶本身的意愿,而是由攻擊者構造,由受害者被動發出的。
CSRF的攻擊過程大致如圖:
CSRF攻擊存在的道理
一種攻擊方式之所以能夠存在,必然是因為它能夠達到某種特定的目的。比如:通過程序中的緩沖區溢出漏洞,我們可以嘗試控制程序的流程,使其執行任意代碼;通過網站上的SQL注入漏洞,我們可以讀取數據庫中的敏感信息,進而獲取Webshell甚至獲取服務器的控制權等等。而CSRF攻擊能夠達到的目的是使受害者發出由攻擊者偽造的請求,那么這有什么作用呢?
顯然,這種攻擊的威力和受害者的身份有著密切的聯系。說到這兒我們可以思考一下,攻擊者之所以要偽造請求由受害者發出,不正是想利用受害者的身份去達到一些目的嗎?換句話說,受害者身上有達到這個目的所必需的條件,
而這些必需的條件在Web應用中便是各種各樣的認證信息,攻擊者就是利用這些認證信息來實現其各種各樣的目的。
下面我們先看幾個攻擊場景。
(1)場景一:
在一個bbs社區里,用戶在發言的時候會發出一個這樣的GET請求:
#!html
GET /talk.php?msg=hello HTTP/1.1
Host: www.bbs.com
…
Cookie: PHPSESSID=ee2cb583e0b94bad4782ea
(空一行)
這是用戶發言內容為“hello”時發出的請求,當然,用戶在請求的同時帶上了該域下的cookie,于是攻擊者構造了下面的csrf.html頁面:
#!html
<html>
<img src=http://www.bbs.com/talk.php?msg=goodbye />
</html>
可以看到,攻擊者在自己的頁面中構造了一個發言的GET請求,然后把這個頁面放在自己的服務器上,鏈接為
http://www.evil.com/csrf.html。之后攻擊者通過某種方式誘騙受害者訪問該鏈接,如果受害者此時處于登錄狀態,就會帶上bbs.com域下含有自己認證信息的cookie訪問
http://www.bbs.com/talk.php?msg=goodbye,結果就是受害者按照攻擊者的意愿提交了一份內容為“goodbye”的發言。
有人說這有什么大不了的,好,我們再看看另一個場景下的CSRF攻擊。
(2)場景二:
在一個CMS系統的后臺,發出下面的POST請求可以執行添加管理員的操作:
#!html
POST /manage.php?act=add HTTP/1.1
Host: www.cms.com
…
Cookie: PHPSESSID=ee2cb583e0b94bad4782ea;
is_admin=234mn9guqgpi3434f9r3msd8dkekwel
(空一行)
uname=test&pword=test
在這里,攻擊者構造了的csrf2.html頁面如下:
#!html
<html>
<form action="/manage.php?act=add" method="post">
<input type="text" name="uname" value="evil" />
<input type="password" name="pword" value="123456" />
</form>
<script>
document.forms[0].submit();
</script>
</html>
該頁面的鏈接為
http://www.evil.com/csrf2.html,攻擊者誘騙已經登錄后臺的網站管理員訪問該鏈接(比如通過給管理員留言等方式)會發生什么呢?當然是網站管理員根據攻擊者偽造的請求添加了一個用戶名為evil的管理員用戶。
通過這些場景我們可以看到,CSRF攻擊會根據場景的不同而危害迥異。小到誘使用戶留言,大到垂直越權進行操作。這些攻擊的請求都是跨域發出,并且至關重要的一點,都是在受害者的身份得到認證以后發生的。
CSRF的防御
要防御CSRF攻擊,我們就要牢牢抓住CSRF攻擊的幾個特點。
首先是“跨域”,我們發現CSRF攻擊的請求都是跨域的,針對這一特點,我們可以在服務端對HTTP請求頭部的Referer字段進行檢查。一般情況下,用戶提交的都是站內的請求,其Referer中的來源地址應該是站內的地址。至關重要的一點是,前端的JAVAScript無法修改Referer字段,這也是這種防御方法成立的條件。
不過需要說明的是,有的時候請求并不需要跨域,比如我們后面講到的結合XSS進行攻擊的時候,有的時候甚至沒有Referer字段…,這些也是使用這種防御方法的弊病所在。
第二點是“偽造”,這也是CSRF攻擊的核心點,即偽造的請求。我們來想一下,攻擊者為什么能夠偽造請求呢?換句話說,攻擊者能夠偽造請求的條件是什么呢?縱觀之前我們偽造的所有請求,無一例外,請求中所有參數的值都是我們可以預測的,如果出現了攻擊者無法預測的參數值,那么將無法偽造請求,CSRF攻擊也不會發生。基于這一點,可以使用添加驗證碼和使用一次性token的方式防御此類攻擊,但是正如世界上沒有完美的系統一樣,也沒有完美的防御方式,都是在不斷的變化與改進當中。
從上面的例子我們可以看出,制造釣魚網站,理論上可以獲取你瀏覽器保存的幾乎所有數據。所以,不信任的網站,不要輕易點擊。上面的例子也僅僅只是csrf最最基礎的應用,但是如果是此類攻擊,也逃不過使用這種方式。只不過會使用這種方式再加各種類型的變種,或結合其他的攻擊方式,對其進行攻擊。