從開發角度淺談CSRF攻擊及防禦

從開發角度淺談CSRF攻擊及防禦

來自專欄 226safe Team

本文作者:226safe Team - Poacher

226團隊交流群:673441920

1.前言:

這篇文章在很早之前已經發布出來過了,現在只是以舊數據的形式重新寫出來。

2.什麼是CSRF?

CSRF可以叫做(跨站請求偽造),咱們可以這樣子理解CSRF,攻擊者可以利用你的身份你的名義去發送(請求)一段惡意的請求,從而導致可以利用你的賬號(名義)去購買商品、發郵件,惡意的去消耗賬戶資源,導致的一些列惡意行為,CSRF可以簡單分為Get型與Post型兩種。

2-1.GET型CSRF

看到這個名字,很明顯是發送GET請求導致的。簡單來說:GET型的CSRF利用非常簡單,通常只要發送一段HTTP請求。如果一個網站某個地方的功能,比如(用戶修改自己郵箱)是通過GET進行請求修改的話。如下例:

bugsafe.cn/user.php? //這裡我們可以看出這個網址是通過get型去對用戶的郵箱進行修改。後面&email=226@226.com 是關鍵的地方。當我們發現沒有做任何處理之後,我們將可以去構造一段代碼。

只要把它email參數後面的值進行修改。。之後構造一個代碼,或者直接一串URL發過去(正常人應該不會這樣)。如下例:

bugsafe.cn/user.php? //只要這個id的用戶觸發了這URL即可成功修改。攻擊者可自行修改id,發送該id用戶也可以修改。觸發後即可成功修改到這個用戶的email。

2-2.POST型CSRF

POST型CSRF簡單來說,通過POST請求去觸發代碼造成漏洞。還是一樣,舉個例子 比如在一個教育視頻網站平台。在普通用戶的眼中,點擊網頁->打開試看視頻->購買視頻 是一個很正常的一個流程。可是在攻擊者的眼中可以算正常,但又不正常的,當然不正常的情況下,是在開發者安全意識不足沒有進行處理所造成。攻擊者在購買處抓到購買時候網站處理購買(扣除)用戶餘額的地址。

比如:bugsafe.cn/coures/user/ //通過buy.php處理購買(購買成功)的信息,這裡的25532為視頻ID。那麼攻擊者現在構造一個表單(form.html),如:

<form action="http://www.bugsafe.cn/coures/user/handler/25332/buy.php" method="post"> <input type="submit" value="提交" /> <script> document.forms[0].submit(); </script> //自動提交 </form>

構造好form表單後,攻擊者將form.html上傳至一台伺服器上,如:bugsafe.cn/form.html

發送給受害者,只要受害者正在登陸當前教育網站的時候,打開攻擊者發送的頁面,那麼代碼則自動觸發,自動購買了id為25332的視頻。從而導致受害者餘額扣除,被攻擊者惡意消耗用戶餘額。如果網站很不嚴謹,那麼只要把id改了,就可以任意的去惡意購買任何視頻。消耗受害者的財產,從而導致用戶財產安全受影響。

3.CSRF的原理

發現漏洞可利用處->構造(搭建)代碼->發送給用戶(管理員)->觸發代碼(發送請求)……

從這個利用的一個流程中,我們可以發現,攻擊者僅僅只是做了兩處工作.第一處是:發現漏洞利用處,,第二處就是構造利用代碼以及發送至用戶(管理員)。

4.在開發中如何簡單防禦CSRF(PHP)

其實防禦CSRF有很多種 如:驗證碼、驗證Referer、以及驗證token,對特殊參數進行加密。

但是如果使用驗證碼去避免CSRF的話,那麼這樣會驗證的影響用戶的體驗,因為用戶不會每個操作都去輸入驗證碼(會很煩)。

Refer的話在特殊情況下也是不靠譜的(伺服器端出的問題)。

那麼目前只有token是被大多網站去使用的。因為可以避免用戶體驗的問題發生。同樣伺服器邊問題也發生也不會很多。

那麼接下來就開始介紹在PHP開發中如何去簡單的生成token,避免CSRF。我們可以通過PHP中函數(rand生成隨機數+uniqid生成一個唯一id+time時間戳)最後在講這幾個生成的值用md5加密。接下來來說說如何去生成:

首先先開啟session會話

session_start(); //開啟session會話

然後隨機生成一段值(這個值就是token值) 備註:其實這樣子生成不是最嚴謹的。

$safe226 = md5(time() . uniqid() . rand(1,99999)); //輸入一個隨機數值

輸出看看

接下來,需要做的就是把生成出來的token丟進session裡面。

我們驗證的其實是存到session裡面的token是否與用戶提交上來的token值一致。如果一致則成功,否則則失敗。我們準備一個表單,用於傳遞用戶提交請求的一個token。

<input type="hidden" value="<?php echo $_SESSION[226_tonken]; ?>">

把token提交到test.php里去處理!

其實就是將session裡面的值丟進隱藏表單裡面。當用戶提交的時候一起提交過來驗證,驗證是否與session裡面的token相同。

來感受下。

接下來只需要去判斷用戶傳遞過來的token值是否和session裡面的值一致(這裡使用簡單判斷,其實原理都是一樣的)。

if (isset($_SESSION[226_token]) && isset($_POST[token])) { if ($_SESSION[226_token] === $_POST[token]) { //這裡是驗證成功後所寫代碼 echo 購買成功; } else { echo 請勿非法操作!判斷是否一致; } } else { echo 請勿非法操作!判斷是否存在; }

接下來嘗試利用下。這裡已知道結構。所以直接構造一個表單。

根據代碼情況 就是當我們構造的利用代碼,沒有傳遞token或者token不一致的時候:

<form action="http://127.0.0.1/test/test.php" method="post"> <input type="submit" value="提交" /> </form>

這裡兩個列印是在test.php裡面列印 沒有去掉print_r(無視就好),當利用時候會發現沒有傳遞token。則會提示錯誤!

接下來看,完全一致的時候。會提示的是什麼:

當通過驗證的時候。會發現已經驗證成功。購買成功。

PS:本文如有爭議地方,歡迎指出。很早之前的文章,懶得再去改動。在放上來的過程中也大概看了下,發現是有很多瑕疵存在的。


推薦閱讀:

關於double free的問題?
安卓開發/反編譯工具中多存在嚴重漏洞
50萬美元收購加密通訊類APP漏洞,真值!

TAG:CSRF | 漏洞挖掘 | Web漏洞 |