PHP程式碼審計實戰思路淺析
*本文原創作者:wnltc0,本文屬FreeBuf原創獎勵計劃,未經許可禁止轉載
戰略性的思考而非戰術
對於面向過程寫法的程式來說,最快的審計方法可能時直接丟seay審計系統裡,但對於基於mvc模式的程式來說,你直接丟seay審計系統的話,那不是給自己找麻煩嗎?
像面向過程寫法的程式,可以找下它的公共函式檔案有啥可以利用的不,然後就是丟seay審計系統。
而對於基於mvc寫法的程式來說,跟讀他的入口檔案,瞭解整個程式的執行流程跟目錄結構,之後再深入去了解它的核心類庫,如果核心類庫存在漏洞的話,那在這套程式中找出個漏洞的希望那不是一般的大啊!瞭解了整個框架執行流程後,也沒從核心類庫中發現什麼可利用的點的話,這時就可以從功能點入手了(這時可以把原始碼丟進seay原始碼審計系統了)。
一套組合拳打下了後還是沒找到漏洞咋辦?沒事,換套程式繼續。如果換了n套程式都找不出來,那就換個人吧……
實戰環節
目標:某開源cms(icms) 環境:win+phpstudy+sublime
大概目錄結構長這樣
├── app應用 ├── cache快取 ├── coreicms程式入口 ├── iPHPiphp框架檔案 ├── public公共資源 ├── res使用者資源 └── template模板
開啟index.php
發現載入了一個icms.php,然後呼叫了iCMS::run()方法(如果你第一反應是以為iCMS.php是個類檔案,那你後面的審計估計有點難受。)
跟進iCMS.php
該處載入了配置跟框架檔案,繼續跟進iPHP.php
載入幾個框架檔案,然後呼叫iPHP::bootstrap()方法,這回差不多了,繼續跟進iPHP::bootstrap()
該處做了些環境配置,然後就是呼叫核心的iWAF、iSecurity類來一下全域性過濾(iWAF這些先跟),看到這可有有的小夥伴又有疑惑了,iWAF什麼時候載入進來了啊?
看到48行的spl_autoload_register函數了沒,再具體點,看到56行那個autoload了沒
這也沒看到哪有include、require之類的啊,怎麼載入進來的?別急,繼續跟進57行的self::auto_require
沒錯就是這了,不過程式碼太長了就不貼了,大概就是判斷傳來的類名中是否有Admincp或者App,如果沒有就載入app/xx/xx.class.php,如果有Admincp則載入app/xx/xx.Admincp.php,如果有App則載入app/xx/xx.app.php,如果有Func則載入app/xx/xx.func.php,如果以上都不滿足則去iPHP/core/下找
iPHP::bootstrap()大概知道它幹了什麼了,再回頭去看看iCMS::init()
大概就是初始化配置資訊,繼續往回看,跟進iCMS::run()
繼續跟進iPHP::run
(程式碼有點長)大概就是從post或get獲取應用名,載入類跟例項化類,呼叫方法等
劃重點了(後面會用到),這裡的檔名格式是xx.app.php,類名是xxApp,其實整套程式並不止index.php這一個入口檔案,還有admincp.php、user.php等,其中載入的檔名格式跟類名都是不一樣的,比如:訪問index.php載入的是xx.app.php的xxApp類,訪問admincp.php載入的xx.admincp.php的xxAdmincp類
跟完入口檔案後,對整個框架是怎麼執行的,都有了個大概的瞭解,接下來可以去深入瞭解了
我跟啊跟,發現核心類中的iHttp類的remote方法有點意思,在iPHP/core/iHttp.class.php 130行
remote方法封裝了curl,用來獲取遠端頁面內容,整個方法並沒有對url進行任何限制或過濾,如果呼叫這個方法前也沒用對url進行限制的話,那ssrf就跑不了了
全域性搜尋下看哪呼叫了這個方法,而remote是個靜態方法,呼叫格式為iHttp::remote,所以直接搜這個就可以了
我想找前臺的漏洞,so,直接看哪個的檔名格式類似xx.app.php就好啦
找啊找,僅發現前臺只有一處呼叫了該方法
找到之後,跟進去看看
把$avatar傳了進去,繼續往上翻翻,看有沒有啥過濾
一直往上翻,只看到這句
會不會在iSecurity::escapeStr這做了限制呢?繼續跟進去看看
貌似沒有對url做限制!!!
再往上翻翻,看看是哪個方法
這回穩了,手動構造資料包
解釋下個欄位:
secode為驗證碼,可從 ofollow,noindex" target="_blank">http://127.0.0.1/icms/public/api.php?app=public&do=seccode 獲得,驗證碼資訊存在cookie裡,只要cookie不變,驗證碼就可一直用。
username跟nickname每次請求都要改變,avatar為傳入的url,這個漏洞還有兩處有點蛋疼的地方,第一,username跟nickname每次都要改變,而且這些值都是會存進資料庫的;第二,這裡的ssrf是沒有回顯。
使用dict來舉個例子,訪問一個未開啟埠時如下
訪問一個開啟的埠時如下
如果上述說的都做完還沒發現漏洞,那可以嘗試丟到seay原始碼審計系統,或者根據功能點進行審計,找找邏輯漏洞
如果做完上述操作後再用軟體來輔助,會輕鬆的多,比如,seay原始碼審計系統掃出來如下
拿第二條距離,漏洞描述是referer偽造會引起sql,點選瞅瞅
看到referer先進入了iSecurity::escapeStr,然後再進入iDB::insert,通過前面的審計我知道 iSecurity::escapeStr對單引號等做了過濾,所以普通的sql注入是沒希望了,只能看看還有沒有其他方式能結合利用(我記得這是有注入的……)
如果我是一上來就用軟體的話,那我現在可能還在一步一步的追一個函式,這樣會增加不少功夫
本文到這就結束了,emmm!
*本文原創作者:wnltc0,本文屬FreeBuf原創獎勵計劃,未經許可禁止轉載