某團購CMS的Getshell操作代碼審計

原創作者:會上樹的豬

聲明:作者初衷用於分享與普及網絡知識,若讀者因此作出任何危害網絡安全行爲後果自負,與合天智匯及原作者無關。

0x00 寫點廢話

在滲透測試中,獲取一個webshell應該是我們不屑的追求,今天要通過這個CMS從代碼的角度看一下可利用的getshell的方法。這一次的代碼審計需要藉助工具來定位可能存在的漏洞點,選擇Seay源代碼審計系統。步入正題。

0x01文件上傳getshell:

圖11、/kindupload.php:通過獲取文件最後一個擴展名進行白名單匹配,且添加隨機數命名新文件名,應該不存在文件上傳漏洞。
圖22、/upload.php:此文件屬於測試文件
圖33、include/function/common.php:關於imagenulljpgimage變量的來源有兩個,爲null時強制轉換jpg格式,當對有圖片項目進行編輯時,image變量就是之前上傳的文件地址,這樣的話想進行任意文件上傳應該就沒有可能了。
圖4

0x02 文件寫入+文件包含getshll:

在進行任意文件刪除/讀取/修改漏洞審計時發現支付日誌位置可以向日志文件寫入任意內容:漏洞位置:/alifast/alipay.function.php
圖5根據定位,可以找到logResult函數:
圖6可以看到其中的wordcheck便log.txt便getshellword變量未經過任何check便寫入到log.txt文件中(此處寫入文件可能比較雞肋,但如果可以找到任意文件包含,便可以直接getshell)而其中word變量來源於對函數的引用,我們全局搜索一下看有哪些地方調用了logResult函數:
圖7可以找到一處調用,在/alifast/lib/alipay_notify_class.php文件中:
圖8
通過verifyNotify函數,當POST數據不爲空時就會調用logResult函數進行日誌寫入,那之後就轉到查找何處調用了verifyNotify函數,找到一處調用:/alifast/returnadd_url.php
圖9圖10而且可以發現此處文件應該不需要登錄便可以直接訪問:
圖11之後我們傳入一個payload,然後開啓DEBUG調試一下,看一下參數傳遞:
圖12圖13最後可以看一下log.txt文件,成功寫入payload:
圖14這需要結合文件讀取漏洞才能利用,否則寫入到txt文件屬於雞肋,之後便通過對掃描到的可能存在文件包含漏洞的點進行驗證,未發現可利用的文件包含漏洞,上面這個任意寫入真的雞肋了。
圖15不過作爲一個搞信息安全的弱雞,我是不會放棄的。
圖16

0x03後臺通過修改模板getshell:

感覺模板渲染位置最容易存在代碼執行漏洞了,之前審計一些其他的CMS也在類似模板渲染位置發現了漏洞,導致getshell。因爲系統存在很多模板,便只舉一個模板當作栗子。
此處漏洞位置:/include/function/template.php
圖17在__parse函數中存在preg_replace函數通過e參數進行代碼執行。
我們先看在哪些地方對__parse函數進行了調用:
圖18在同文件下58行,通過__tempate函數進行調用。
圖19再搜索有哪些地方對__template函數進行了調用:
圖20
在/include/function/common.php文件下存在對__template函數的調用:
圖21
最後就是看有哪些地方調用了template函數:
圖22
這些調用基本都是進行模板加載的位置,我們先隨便找一處:(團購信息提交)
圖23
接下來還是要開啓debug,然後跟蹤一下程序執行的邏輯:
1、訪問鏈接,觸發模板解析函數:注意此處採用的include的方式進行模板加載。
圖24
2、進入template函數之後,會根據傳遞的參數加載不同的模板。
圖25
3、當進入__template函數之後要先根據傳遞的參數加載模板的絕對位置,這裏注意,存在一個模板和一個編譯後的模板,模板是.html文件,而編譯後的模板是.php文件,程序在此處將模板文件路徑存在變量tfiletfile,編譯後的模板文件路徑存在變量cFile,之後會利用filemtime函數來比較兩個文件的修改時間,如果模板的修改時間小於編譯後的模板文件,那說明已經對模板進行過編譯,直接返回編譯後的模板文件路徑。反之纔會調用__parse函數對模板進行重新編譯。
圖26
根據上面的分析,我們要找到可以修改模板的功能點,不然此處漏洞便無法利用,因爲無法滿足文件修改時間的檢查,除非站長剛好改了模板文件。不過一般站點都提供了模板修改功能,這個CMS也不例外:
圖27
既然後臺可以修改模板文件,那就保證模板文件修改時間大於編譯後的模板文件,這樣就會進入重新編譯環節。
圖28
我們通過第20行的preg_replace來進行分析:
preg_replace("/<!--\s*\${(.+?)}\s*-->/ies", “__replace(’<?php \\1; ?>’)”, $fileContent);
圖29
這個正則表達式會怎麼匹配不太好說,直接舉一下編譯前和編譯後的栗子出來就能明白了:
圖30圖31
上面那個正則是如何處理的應該就清楚了。接下來還是繼續debug,跟蹤模板渲染的具體邏輯:
圖32
通過正則表達式將模板進行渲染,然後通過file_put_content函數將內容全部寫入到渲染後的模板,寫入成功則返回true。
圖33
值得注意的是最後返回的是渲染後的模板的物理路徑,然後通過include方式加載模板,此時可以看到模板已經通過正則全部替換爲php代碼。
圖34
在這個地方存在一個之前的想法錯誤,其實並不是通過preg_replace來進行代碼執行,因爲通過/e參數調用的函數是__replace方法,只進行了簡單的替換,最後還是通過文件包含的方法來包含存在惡意代碼的模板。
圖35圖36
既然已經清楚模板渲染的流程,接下來嘗試getshell操作,首先將模板修改成如下形式:記得閉合雙引號,括號等等。
圖37
通過編譯函數之後模板應該是下面這個樣子的:
圖38
最後通過include包含這個含有惡意代碼的模板:
圖39

0x04數據庫備份getshell:

在一般系統中通常會存在數據庫備份的功能,在滲透測試中利用數據庫備份getshell也是常用操作,在這個CMS系統中同樣發現了數據庫備份與還原功能。
圖40
但是此處數據庫備份的文件是默認的用戶不可控的,未發現將惡意代碼備份到.php文件當中的操作:
圖41
但是在之後對從本地文件恢復數據庫的功能進行審計發現,此處存在任意SQL語句執行,相當於給我們提供了一個執行任意SQL語句的接口,那麼便可以嘗試通過SQL命令導出文件getshell和MySQL日誌getshell。先來看一下程序邏輯:
在數據庫恢復功能提供了從本地文件恢復的功能:
圖42
當本地文件上傳到服務器,會通過一個backup_import的函數執行文件內的SQL語句:
圖43
我們跟蹤一下這個函數:
圖44
可以看到從文件中讀取到SQL語句之後只去掉了幾個特殊符號,便通過DB::Query方法直接執行,其中可以再看一下Query方法:未經過任何處理,直接執行SQL語句。
圖45
已經明白程序的運行邏輯,那麼我們便只要構造可以getshell的SQL語句,然後通過備份還原的功能執行SQL語句便能夠成功getshell。

上面說MySQL有兩種常用的方法getshell:文件導出和日誌記錄。因爲新版的MySQL添加了secure_file_priv參數對文件導入導出進行了限制,這個參數需要修改數據庫配置文件,利用困難。
圖46
所以爲了提高成功率優先選擇利用日誌功能getshell。這裏還是先介紹一下利用log日誌getshell。在MySQL日誌功能中:
1、General_log 指的是日誌保存狀態,一共有兩個值(ON/OFF)ON代表開啓 OFF代表關閉。
2、General_log_file 指的是日誌的保存路徑。
3、關於開啓general_log參數的作用:
a)開啓它可以記錄用戶輸入的每條命令,會把其保存再general_log_file指定的目錄下,就是日誌文件。這個參數是可以直接通過mysqld進行設置。
b)我們的利用的思路是開啓general_log之後把general_log_file的值修改爲我們網站默認路徑下一個自定義的php文件中,然後我們通過log日誌進行寫入一句話後門到上面去,然後再進一步利用。
通過上面的介紹我們知道要實現日誌getshell,要做的以下三步:開啓日誌功能,重定義日誌輸出文件(需要絕對路徑),執行惡意SQL語句寫入日誌,具體SQL語句如下:
圖47
之後上傳文件執行SQL語句,然後在之前設置的日誌路徑下便可以看到帶有惡意payload的日誌文件了:
圖48圖49
訪問一下鏈接,成功getshell
圖50

0x05 收尾:

還是來點騷話收尾,上述只是我找到的一些getshell的操作,肯定還會有其他getshll的操作沒有被我發現。但是用代碼審計的方式從代碼角度去看待漏洞形成的原因對漏洞的理解還是有很大幫助的,還是那句話,代碼審計一時爽,一直審計一直爽,大家也可以加入代碼審計的大軍,有興趣和我這個菜雞一起成長進
步。
實操學習:代碼審計利器-Seay源代碼審計系統

圖51

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章