一、CSRF介紹
CSRF(Cross-site request forgery)
跨站請求僞造,也被稱為“OneClick Attack”或者Session Riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。

<img src="https://img0.tuicool.com/2ArA73m.jpg!web" class="alignCenter" alt="CSRF攻擊與防禦,web安全的第一防線(源碼,實戰,5分鐘科普文)" /> </p>
上圖為CSRF攻擊的一個簡單模型,使用者通路惡意網站B,惡意網站B傳回給使用者的HTTP資訊中要求使用者通路網站A,而由于使用者和網站A之間可能已經有信任關系導緻這個請求就像使用者真實發送的一樣會被執行。
二、CSRF攻擊的危害
攻擊者盜用了你的身份,以你的名義發送惡意請求,對伺服器來說這個請求是完全合法的,但是卻完成了攻擊者所期望的一個操作,比如以你的名義發送郵件、發消息,盜取你的賬号,添加系統管理者,甚至于購買商品、虛拟貨币轉賬等。
如果CSRF發送的垃圾資訊還帶有蠕蟲連結的話,那些接收到這些有害資訊的好友萬一打開私信中的連接配接就也成為了有害資訊的散播着,這樣數以萬計的使用者被竊取了資料種植了木馬。整個網站的應用就可能在瞬間奔潰,使用者投訴,使用者流失,公司聲譽一落千丈甚至面臨倒閉。曾經在MSN上,一個美國的19歲的小夥子Samy利用css的background漏洞幾小時内讓100多萬使用者成功的感染了他的蠕蟲,雖然這個蠕蟲并沒有破壞整個應用,隻是在每一個使用者的簽名後面都增加了一句“Samy 是我的偶像”,但是一旦這些漏洞被惡意使用者利用,後果将不堪設想,同樣的事情也曾經發生在新浪微網誌上面。
如下:其中Web A為存在CSRF漏洞的網站,Web B為攻擊者建構的惡意網站,User C為Web A網站的合法使用者。
三、CSRF攻擊原理及過程

<img src="https://img0.tuicool.com/j6rIbuZ.jpg!web" class="alignCenter" alt="CSRF攻擊與防禦,web安全的第一防線(源碼,實戰,5分鐘科普文)" /> </p>
1 、使用者C打開浏覽器,通路受信任網站A,輸入使用者名和密碼請求登入網站A;
2、在使用者資訊通過驗證後,網站A産生Cookie資訊并傳回給浏覽器,
此時使用者登入網站A成功,可以正常發送請求到網站A;
3、使用者未退出網站A之前,在同一浏覽器中,打開一個TAB頁通路網站B;
4、網站B接收到使用者請求後,傳回一些攻擊性代碼,
并發出一個請求要求通路第三方站點A;
5.、浏覽器在接收到這些攻擊性代碼後,根據網站B的請求,
在使用者不知情的情況下攜帶Cookie資訊,向網站A送出請求。
網站A并不知道該請求其實是由B發起的,是以會根據使用者C的Cookie資訊以C的權限處理
該請求,導緻來自網站B的惡意代碼被執行。
複制
舉例:
簡單版:
假如部落格園有個加關注的GET接口,blogUserGuid參數很明顯是關注人Id,如下:

<img src="https://img0.tuicool.com/ru2QJff.jpg!web" class="alignCenter" alt="CSRF攻擊與防禦,web安全的第一防線(源碼,實戰,5分鐘科普文)" /> </p>
那我隻需要在我的一篇博文内容裡面寫一個img标簽:

<img src="https://img2.tuicool.com/RfUjMrR.jpg!web" class="alignCenter" alt="CSRF攻擊與防禦,web安全的第一防線(源碼,實戰,5分鐘科普文)" /> </p>
那麼隻要有人打開我這篇博文,那就會自動關注我。
更新版:
假如部落格園還是有個加關注的接口,不過已經限制了隻擷取POST請求的資料。這個時候就做一個第三方的頁面,但裡面包含form送出代碼,然後通過QQ、郵箱等社交工具傳播,誘惑使用者去打開,那打開過部落格園的使用者就中招了。
在說例子之前要糾正一個iframe問題,有人會直接在第三方頁面這樣寫。如下:

<img src="https://img1.tuicool.com/ieAJBjQ.jpg!web" class="alignCenter" alt="CSRF攻擊與防禦,web安全的第一防線(源碼,實戰,5分鐘科普文)" /> </p>
這樣是用問題的,由于同源政策的原因,iframe内容根本加載不出來,是以裡面form送出當然不會執行。
PS:我嘗試了chrome、IE11、Firefox,情況都是這樣。
是以可以用嵌多一層頁面方式解決,如下:
第一個展示頁面(test):

<img src="https://img1.tuicool.com/zEZnInq.jpg!web" class="alignCenter" alt="CSRF攻擊與防禦,web安全的第一防線(源碼,實戰,5分鐘科普文)" /> </p>
第二個隐藏頁面(test2):

<img src="https://img0.tuicool.com/ni6fMzn.jpg!web" class="alignCenter" alt="CSRF攻擊與防禦,web安全的第一防線(源碼,實戰,5分鐘科普文)" /> </p>
這樣就可以解決了,有人會問為什麼要加多一層iframe,因為不嵌iframe頁面會重定向,這樣就降低了攻擊的隐蔽性。另外我們test頁面不使用XMLHTTPRequest發送POST請求,是因為有跨域的問題,而form可以跨域post資料。
進階版:
假如部落格園還是有個加關注的接口,已經限制POST,但博文内容是直接貼進HTML(未過濾),那就遭受XSS攻擊。那麼就可以直接把上面代碼嵌入博文,那麼隻要有人打開我這篇博文,還是會自動關注我,這組合攻擊方式稱為XSRF。
四、CSRF漏洞檢測
檢測CSRF漏洞是一項比較繁瑣的工作,最簡單的方法就是抓取一個正常請求的資料包,去掉Referer字段後再重新送出, 如果該送出還有效,那麼基本上可以确定存在CSRF漏洞 。
随着對CSRF漏洞研究的不斷深入,不斷湧現出一些專門針對CSRF漏洞進行檢測的工具,如CSRFTester,CSRF Request Builder。
以CSRFTester工具為例,CSRF漏洞檢測工具的測試原理如下:
使用CSRFTester進行測試時,首先需要抓取我們在浏覽器中通路過的所有連結以及所有的表單等資訊,然後通過在CSRFTester中修改相應的表單等資訊,重新送出,這相當于一次僞造用戶端請求。如果修改後的測試請求成功被網站伺服器接受,則說明存在CSRF漏洞,當然此款工具也可以被用來進行CSRF攻擊。
五、CSRF漏洞防禦
目前防禦 CSRF 攻擊主要有三種政策:驗證 HTTP Referer 字段;在請求位址中添加 token 并驗證;在 HTTP 頭中自定義屬性并驗證。
1、盡量使用POST,限制GET
GET接口太容易被拿來做CSRF攻擊,看第一個示例就知道,隻要構造一個img标簽,而img标簽又是不能過濾的資料。
接口最好限制為POST使用,GET則無效,降低攻擊風險。
當然POST并不是萬無一失,攻擊者隻要構造一個form就可以,但需要在第三方頁面做,這樣就增加暴露的可能性。
2、浏覽器Cookie政策
IE6、7、8、Safari會預設攔截第三方本地Cookie(Third-party Cookie)的發送。
但是Firefox2、3、Opera、Chrome、Android等不會攔截,是以通過浏覽器Cookie政策來防禦CSRF攻擊不靠譜,隻能說是降低了風險。
PS:Cookie分為兩種
Session Cookie(在浏覽器關閉後,就會失效,儲存到記憶體裡),
Third-party Cookie(即隻有到了Exprie時間後才會失效的Cookie,這種Cookie會儲存到本地)。
PS:另外如果網站傳回HTTP頭包含P3P Header,那麼将允許浏覽器發送第三方Cookie。
3、加驗證碼
驗證碼,強制使用者必須與應用進行互動,才能完成最終請求。在通常情況下,驗證碼能很好遏制CSRF攻擊。
但是出于使用者體驗考慮,網站不能給所有的操作都加上驗證碼。
是以驗證碼隻能作為一種輔助手段,不能作為主要解決方案。
4、Referer Check
Referer Check在Web最常見的應用就是“防止圖檔盜鍊”。
同理,Referer Check也可以被用于檢查請求是否來自合法的“源”(Referer值是否是指定頁面,或者網站的域),如果都不是,那麼就極可能是CSRF攻擊。
但是因為伺服器并不是什麼時候都能取到Referer,是以也無法作為CSRF防禦的主要手段。
但是用Referer Check來監控CSRF攻擊的發生,倒是一種可行的方法。
5 、Anti CSRF Token
現在業界對CSRF的防禦,一緻的做法是使用一個Token(Anti CSRF Token)。
例子:
1、使用者通路某個表單頁面。
2、 服務端生成一個Token,放在使用者的Session中,或者浏覽器的Cookie中。
3、在頁面表單附帶上Token參數。
4、使用者送出請求後, 服務端驗證表單中的Token是否與使用者Session(或Cookies)中的Token一緻,一緻為合法請求,不是則非法請求。
這個Token的值必須是随機的,不可預測的。由于Token的存在,攻擊者無法再構造一個帶有合法Token的請求實施CSRF攻擊。另外使用Token時應注意Token的保密性,盡量把敏感操作由GET改為POST,以form或AJAX形式送出,避免Token洩露。
注意:
CSRF的Token僅僅用于對抗CSRF攻擊。當網站同時存在XSS漏洞時候,那這個方案也是空談。
是以XSS帶來的問題,應該使用XSS的防禦方案予以解決。
特别是在一些論壇之類支援使用者自己發表内容的網站,黑客可以在上面釋出自己個人網站的位址。由于系統也會在這個位址後面加上 token,黑客可以在自己的網站上得到這個 token,并馬上就可以發動 CSRF 攻擊。為了避免這一點,系統可以在添加 token 的時候增加一個判斷,如果這個連結是鍊到自己本站的,就在後面添加 token,如果是通向外網則不加。不過,即使這個 csrftoken 不以參數的形式附加在請求之中,黑客的網站也同樣可以通過 Referer 來得到這個 token 值以發動 CSRF 攻擊。這也是一些使用者喜歡手動關閉浏覽器 Referer 功能的原因。
5、在 HTTP 頭中自定義屬性并驗證
這種方法也是使用 token 并進行驗證,和上一種方法不同的是,這裡并不是把 token 以參數的形式置于 HTTP 請求之中,而是把它放到 HTTP 頭中自定義的屬性裡。通過 XMLHttpRequest 這個類,可以一次性給所有該類請求加上 csrftoken 這個 HTTP 頭屬性,并把 token 值放入其中。這樣解決了上種方法在請求中加入 token 的不便,同時,通過 XMLHttpRequest 請求的位址不會被記錄到浏覽器的位址欄,也不用擔心 token 會透過 Referer 洩露到其他網站中去。
然而這種方法的局限性非常大。XMLHttpRequest 請求通常用于 Ajax 方法中對于頁面局部的異步重新整理,并非所有的請求都适合用這個類來發起,而且通過該類請求得到的頁面不能被浏覽器所記錄下,進而進行前進,後退,重新整理,收藏等操作,給使用者帶來不便。另外,對于沒有進行 CSRF 防護的遺留系統來說,要采用這種方法來進行防護,要把所有請求都改為 XMLHttpRequest 請求,這樣幾乎是要重寫整個網站,這代價無疑是不能接受的。
六、最後聊聊XSS
惡意攻擊者往Web頁面裡插入惡意Script代碼,當使用者浏覽該頁之時,嵌入其中Web裡面的Script代碼會被執行,進而達到惡意攻擊使用者的目的。
XSS攻擊分成兩類
來自内部的攻擊:
主要指的是利用程式自身的漏洞,構造跨站語句,如:dvbbs的showerror.asp存在的跨站漏洞。
來自外部的攻擊
主要指的自己構造XSS跨站漏洞網頁或者尋找非目标機以外的有跨站漏洞的網頁。如當我們要滲透一個站點,我們自己構造一個有跨站漏洞的網頁,然後構造跨站語句,通過結合其它技術,如社會工程學等,欺騙目标伺服器的管理者打開。
XSS分為:存儲型和反射型
存儲型XSS:
存儲型XSS,持久化,代碼是存儲在伺服器中的,如在個人資訊或發表文章等地方,加入代碼,如果沒有過濾或過濾不嚴,那麼這些代碼将儲存到伺服器中,使用者通路該頁面的時候觸發代碼執行。這種XSS比較危險,容易造成蠕蟲,盜竊cookie(雖然還有種DOM型XSS,但是也還是包括在存儲型XSS内)。
反射型XSS:
非持久化,需要欺騙使用者自己去點選連結才能觸發XSS代碼(伺服器中沒有這樣的頁面和内容),一般容易出現在搜尋頁面。