1. CSRF實例
CSRF攻擊的主要目的是讓用戶在不知情的情況下攻擊自己已登錄的一個系統,類似於釣魚。如用戶當前已經登錄了郵箱,或bbs,同時用戶又在使用另外一個,已經被坦碧你控制的站點,我們姑且叫它釣魚網站。這讓逗舉個網站上面可能因為某個圖片吸引你,你去點擊一下,此時可能就會觸發一個js的點擊事件,構造一個bbs發帖的請求,去往你的bbs發帖,由於當前你的瀏覽器狀態已經是登陸狀態,所以session登陸cookie信息都會跟正常的請求一樣,純天然的利用當前的登陸狀態,讓用戶在不知情的情況下,幫你發帖或干其他事情。
一句話就是我們利用CSRF攻擊就是借用用戶的身份去執行用戶的操作
先看一個例子(白帽子講web安全),一個刪除搜狐博客的例子,利用CSRF刪除搜狐博客。
正常情況下,登陸搜狐博客後,只需請求這個url,就能把編號156713012的博客文章刪除
我們嘗試利用CSRF漏洞,刪除編號為「156714243」的博客文章。這篇文章標題「test1」.
攻擊者首先在自己的域構造一個頁面:
其內容;
使用了一個<img>標簽,其地址指向了刪除博客文章的鏈接。
攻擊者誘使目標用戶,也就是博客主人「test1test」訪問這個頁面:
該用戶會看到一張無法顯示的圖片,也就是<img>標簽創造的圖片,但無法顯示,然後回頭看搜狐博客:
發現原來存在的標題為『』test1」的文章,已被刪除。
這個刪除博客攻擊文章的請求,是攻擊者偽造的,所以這種攻擊就叫做「跨站點請求偽造」。
下面仿照以上做一個實例,這里利用自己的簡單留言板實施一次CSRF攻擊
前面我們已經講過了,CSRF攻擊是在用戶登錄狀態下,利用用戶身份執行操作,這里就用到了cookie,當用戶正在訪問留言板時,誘導用戶去點開攻擊者偽造的一個網頁(有刪除留言的指令),用戶點開之後便帶著原來的留言板cookie去執行刪除留言這條指令,當用戶返回之後發現原來留言信息沒了。
這是登錄界面,輸入用戶名進去後
看一下用戶的cookie吧
當然這里是自己的cookie,已經能看到了指談。
可以看到是post請求以表單的形式提交到delete.php,執行刪除操作找到表單提交的name="ids",也就是ids=1時,我們可以刪除id=1的留言,因為是POST請求,不能用標簽的src屬性,所以需要構建一個POST請求。
攻擊者在自己的伺服器中建立一個HTML文件csrf.html,用JS自動提交POST請求的form表單
這個只是本地測試,現在刪除第三條留言,這個時候只要誘導用戶去訪問 http://127.0.0.1/Myphp/csrf.html 就會刪除該留言,至於用什麼方法,需要攻擊者去精心構造了,只要想像力豐富,就能發揮CSRF強大的破壞力。
當用戶在登錄留言板狀態下去訪問該網頁,,,,
原來的留言沒了
這就是基本的CSRF攻擊。。
2. CSRF(跨域請求偽造)
跨站請求攻擊,簡單地說,是攻擊者通過一些技術手段欺騙用戶的瀏覽器去訪問一個自己曾經認證過的網站並執行一些操作(如發郵件,發消息,甚至財產操作如轉賬和購買商品)。由於瀏覽器曾經認證過,所以被訪問的網站會認為是真正的用戶操作而去執行。這利用了web中用戶身份驗證的一個漏洞:簡單的身份驗證只能保證請求發自某個用戶的瀏覽器,卻不能保證請求本身是用戶自願發出的。
你這可以這么理解CSRF攻擊: 攻擊者盜用了你的身份,以你的名義發送惡意請求。 CSRF能夠做的事情包括:以你名義發送郵件,發消息,盜取你的賬號,甚至於購買商品,虛擬貨幣轉賬……造成的問題包括:個人隱私泄露以及財產安全。
從上圖可以看出,要完成一次CSRF攻擊,受害者必須依次完成兩個步驟:
登錄受信任網站A,並在本地生成Cookie。
在不登出A的情況下,訪問危險網站B。
看到這里,你也許會說:「如果我不滿足以上兩個條件中的一個,我就不會受到CSRF的攻擊」。是的,確實如此,但你不能保證以下情況不會發生:
1.你不能保證你登錄了一個網站後,不再打開一個tab頁面並訪問另外的網站。
2.你不能保證你關閉瀏覽器了後,你本地的Cookie立刻過期,你上次的會話已經結束。
3.上圖中所謂的攻擊網站,可能是一個存在其他漏洞的可信任的經常被人訪問的網站。
1.提交驗證碼
在表單中增加一個隨機的數字或字母驗證碼,通過強制用戶和應用進行交互,來有效地遏制CSRF攻擊。
2.Referer Check(referer:標志請求來源)
檢查如果是非正常頁面過來的請求,則極有可能是CSRF攻擊。
3.token驗證
在 HTTP 請求中以參數的形式加入一個隨機產生的 token,並在伺服器端建立一個攔截器來驗證這個 token,如果請求中沒有
token 或者 token 內容不正確,則認為可能是 CSRF 攻擊而拒絕該請求。
token需要足夠隨機
敏感的操作應該使用POST,而不是GET,以form表單的形式提交,可以避免token泄露。
4. 在 HTTP 頭中自定義屬性並驗證
這種方法也是使用 token 並進行驗證,這里並不是把 token 以參數的形式置於 HTTP 請求之中,而是液春把它放到 HTTP 頭中自定義的屬性里。通過 XMLHttpRequest 這個類,可以一次性給所有該類請求加上 csrftoken 這個 HTTP 頭屬性,並把 token 值蠢埋擾放入其中。這樣解決了上種方法在請求中加入 token 的不便帶旦,同時,通過 XMLHttpRequest 請求的地址不會被記錄到瀏覽器的地址欄,也不用擔心 token 會透過 Referer 泄露到其他網站中去。
csrf過濾器:
referer檢查如果是非正常頁面過來的請求,則極有可能是CSRF攻擊。
自定義請求頭「supporter」,根據電話、郵箱、日期、特殊字元、base64前台加密,後台過濾器解析。
3. CSRF攻擊簡介
CSRF(Cross Site Request Forgery),中文翻譯為跨站請求欺騙攻擊,是一種利用了瀏覽器漏洞的一種攻擊手段,常被黑客用作刷介面的手段。
Cookie是保存在瀏覽器本地的一些數據,通常伺服器會將和用戶有關的數據,如登錄token存放在Cookie中。瀏覽器有一套對Cookie的保護措施,比如Cookie按域(domain)存儲,Cookie在別的域下是不可見的。
瀏覽器中的Cookie按照域(Domain)存儲,不同域下的Cookie彼此不可見。但是從別的域下發來的請求卻能帶上這個域的Cookie。帶上Cookie是好事,但不可避免的產生一些壞結果,因為Cookie中往往存儲了用戶的登錄token,這使得來自別的域的請求自動處於登錄狀態,這意味著別的域的請求能模擬用戶做出任何事情,比如批量發帖,批量刪帖等。
小明是某某社區的用戶
雖然跨域請求能帶上Cookie,但請求前卻無法看到Cookie中的內容,那麼我們只要在Cookie中加上一個欄位(X-CSRF-TOKEN)並在別的地雹輪方如Header中加上一個一模一樣的欄位,在伺服器收到請求時校驗這兩個欄位是否一致,便能防禦CSRF攻擊。
生成X-CSRF-TOKEN有兩種策略:
1.在登錄時由伺服器下發給Cookie。
2.前端通過隨機數生成,當發送請求時,發現Cookie中沒有X-CSRF-TOKEN欄位,便給Cookie加上該欄位。
實踐時我採用了前端隨機生成Token的方法,實現過程中也遇到了一些問題。
1.如何生產Token
通過隨機數生成的Token實際上就是時間戳。這種隨機數是可以被碰撞攻擊的。比如用戶生成了Token就被CSRF,那CSRF中攜帶的Token完全可能野賣與我們生成的Token一致。解決方法是通過伺服器下發的登錄Token+時間戳做一個md5作為X-CSRF-TOKEN。
但這由帶來了另一個問題,像登錄Token這種重要的數據應該設置為http only,即js不可見,這樣才能避免另外一些攻擊,因此最好的辦法實際是採用伺服器下發Token的方式。
2.token放在header中還是放在body里
將Token放在Header中當然是最好的,但在實踐中,使用自定義的Header會帶來一些跨域的問題。頌肆逗瀏覽器在遇到跨域並且請求中有自定義Header時,首先它會向伺服器發送一個Options請求來獲取伺服器的跨域策略,即response中的那幾個header:
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Credentials
Access-Control-Allow-Headers
因此在服務端我們要在Access-Control-Allow-Methods中加上Options,在Access-Control-Allow-Headers中加上X-CSRF-TOKEN。
然而這還不夠,發送Options請求很有可能會失敗,如果你有nginx的話。nginx可能會直接將Options請求給攔下來,導致之後的請求無法執行。