偶然發現的bug————越權訪問漏洞追溯

IT168GB發表於2018-08-31


因為經常需要做一些小的demo,所以掌握一個快速開發框架是十分重要的,我比較習慣使用yii2,而就在寫demo的過程中,最後使用指令碼自動化測試的時候,偶然間發現了不登陸竟然也可以執行邏輯程式碼,這也就是這篇文章的起源。

大家都知道,框架基本都是基於mvc框架的,yii2也不例外,每個框架都有自己封裝好的訪問控制程式碼元件,很多人(也包括我自己)在使用的時候,是不會去具體檢視究竟是怎麼實現的,這也就可能會導致版本更替,或者版本更新了以後,還按照預設寫法來做訪問控制,最終導致了越權漏洞的產生。
在yii中,所有的邏輯程式碼都寫在控制器中,而每一個操作又叫動作,所以在yii中,一個控制器的大概結構就是:

class SiteController extends Controller
{    
    public function actionIndex()
    {        
        return $this->render('index');
     }    
     
     public function actionLogin()
     {
        .........        
        return $this->render('index');
    }
}

 

csrf的防禦

為什麼要先講講csrf的防禦呢?因為我瞭解訪問控制,就是從這裡開始的。前面的幾篇文章分析的cms,也有很多都沒有實現csrf校驗,也算是提供一個比較好的實現方法。

在所有使用yii開發的系統,預設都是開啟了csrf token防禦驗證的,而具體實現這個校驗的途徑,就是使用了一個叫做beforeacton的特殊動作,這個動作會在該控制器的任意動作執行之前執行。
我們具體跟進看一下所有控制器的父類裡面的實現:
可以看到,這裡csrf有兩個關鍵的點:

$this->enableCsrfValidation
!Yii::$app->getRequest()->validateCsrfToken()

上面的是配置,開發者是可以在控制器當中關閉配置來關閉csrf驗證的,下面則是驗證csrf token的函式,我們繼續跟進一下:
透過簡單的檢視,可以看到具體的實現程式碼,這樣就可以實現對開發者和訪問者都透明化的處理,既不會干擾開發者寫正常的邏輯程式碼,也不會影響訪問者的操作,可以說是比較經典的實現csrf校驗的方法。

 

訪問控制的實現

在yii2.0.3版本之前,如果控制器的所有動作都是需要登陸的,那就可以在beforeaction中直接寫上控制程式碼,例如:

但是就是這樣的預設寫法,在前幾天測試的時候卻出現了問題。

簡單測試

我們簡單寫一個demo測試一下,其中的action和beforeaction如下圖:

然後嘗試訪問一下site/test這個動作,按理說這個時候是不會顯示123的,應該渲染index所對應的模板檔案
但是實際情況確實仍舊會列印出來123,這就說明test這個動作還是執行了,越權漏洞也就產生了,如果控制器內部有一些危險的動作,加上這個越權漏洞危害還是比較巨大的。

資料查詢

經過在github上的搜尋,發現這個問題在issue中是有人提到過的,並且官方給出瞭解決方案。

對比分析

可以看到,解決方案是在redirect後面緊接上執行send函式,那我們就來看一下現在這兩個函式:


根據大概的函式名,可以看出來redirect函式只是向瀏覽器傳送了一個302的響應碼,這其實在安全中就和只做了前端驗證是一樣的操作,所以是非常危險的,那我們繼續追蹤一下send函式,他又是怎麼彌補這個問題的呢?
send函式實現了強制傳送302跳轉的功能,並且在最後關閉了當前的連線,這樣就能確保越權不在產生,其實總結一下:

redirect => echo "<script>window.location.href=xxx;</script>";
redirect+send => echo "<script>window.location.href=xxx;</script>";die();

就大概相當於這樣,所以道理是非常淺顯易懂的,但是由於封裝了很多層,所以可能不是很好看出來。 

後記

所以不論是在開發或者是在做安全的過程中,重視開發文件都是非常重要的,嚴格的實現協議,嚴格的按照開發文件實現邏輯,會減少很多漏洞的產生。


本文轉載自:安全客。原文作者:執念於心

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31510736/viewspace-2213302/,如需轉載,請註明出處,否則將追究法律責任。

相關文章