摘要:前言首先聲明這不是,具體齊博版本就不說了,后面應該有人也發(fā)現(xiàn)這個漏洞并且發(fā)出來了。那時候?qū)Ξ敃r的齊博系列進行完整的分析和代碼審計,漏洞不少,挑幾個有意思的發(fā)出來。任意長度最終密文則為由于網(wǎng)絡傳輸字符關(guān)系,齊博這里對進行了一次操作。
前言
首先聲明這不是0day,具體齊博版本就不說了,后面應該有人也發(fā)現(xiàn)這個漏洞并且發(fā)出來了。
本文為篤行日常工作記錄,文章是大概14年國慶節(jié)寫的,一直未公開。那時候?qū)Ξ敃r的齊博系列進行完整的分析和代碼審計,漏洞不少,挑幾個有意思的發(fā)出來~。
一.HMAC簡介HMAC 是密鑰相關(guān)的哈希運算消息認證碼( Hash-based Message Authentication Code),HMAC 運算利用哈希算法,以一個密鑰和一個消息為輸入,生成一個消息摘要作為輸出。
詳細介紹自己google吧。
https://en.wikipedia.org/wiki...
二.齊博CMS HMAC解析見文件inc/function.inc.php 中的mymd5 函數(shù)
/** *加密與解密函數(shù) **/ function mymd5($string, $action = "EN", $rand = ""){ //字符串加密和解密 global $webdb; $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"); return $code; }
開發(fā)人員把加密和解密的算法都合起來在了一起。這里的交換密鑰如下(附帶 rand 隨機變量),且系統(tǒng)安裝時候也會隨機產(chǎn)生參數(shù)$webdb[mymd5] 見 data/config.php:
$secret_string = $webdb[mymd5].$rand."5*j,.^&;?.%#@!"
結(jié)算構(gòu)成的密文信息結(jié)構(gòu)如下如下:
|任意長度密文|固定10字節(jié)hashcode|
總體加密過程概括如下:
Data = 原文 Key = $webdb[mymd5].$rand."5*j,.^&;?.%#@!" HashKey = md5( Data + Key ) HashKey1 = substr( md5(Data),8,10 ) 固定 10 位的 hashcode,簽名用。 EncryptData = HashKey^Data 任意長度 最終密文則為 EncryptData+hashcode 由于網(wǎng)絡傳輸字符關(guān)系,齊博這里對 EncryptData 進行了一次 base64encode 操作。 實際得到的是 base64encode(EncryptData)+hashcode
總體解密過程如下:
Data = 密文 Key = $webdb[mymd5].$rand."5*j,.^&;?.%#@!" DataReal = base64decode( substr( Data, 0, len(Data) – 8 )) 取出真正的密文,并且還原成二進制 HashKey = md5(DataReal + Key) HashKey1 = substr(Data,-8 ) 固定 10 位的 HashKey1,取最后 10 位。 OriginalData = HashKey^ DataReal 還原密文,并不是逆向解密。 最終一步 HashKey1 校驗 如果 md5(OriginalData) 等于 HashKey1 那么則認為這個消息是有效的那么最終明文為 OriginalData
整個交換的過程中對于用戶來說密鑰 Key 是不可見的,根據(jù)明文和密文是不可能直接還原出整個加密的算法,用戶對計算出 10 位 HashKey1 的簽名也是未知的,總體安全性比較高,要暴力破解枚舉則要 16^10 次方的數(shù)量級。
三.齊博類 HMAC 算法爆破的可能性經(jīng)過分析,次算法可能存在一個極大的安全隱患就是計算EncryptData 引入的是 Data 的長度,在長度較短的時候可以進行暴力枚舉。
$len = strlen($key); $code = ""; for ($i = 0; $i < strlen($string); $i++){ $k = $i%$len; $code . = $string[$i] ^ $key[$k];
如果我們構(gòu)造原文Data = ‘ly’ 那么 HashKey1 則可以固定成 c6555942cb ,那么整個加密串應該是 EncryptDatac6555942cb 的形式。只要讓算法滿足 substr( md5(HashKey ^ Data),8,10) 等于 c6555942cb 即可。
又有:
Data = EncryptData^HashKey EncryptData =HashKey ^ Data
我們的明文只有 2 位,那么能構(gòu)造的 EncryptData 是 00~FF 規(guī)模為 16^2 數(shù)量相當可觀,那么暴力枚舉規(guī)模就轉(zhuǎn)換成了 16^len(Data) 復雜度。
四.齊博前臺認證 COOKIES 注入
齊博系統(tǒng)在COOKIE 中使用了 HMAC,COOKIE 產(chǎn)生和使用其實都是服務端做的工作,其實沒有第一章所說的明顯的客戶端/服務端模式交換密鑰,這里的場景是廣義的 C/S模式,類似UC_Client/UC_Server,在業(yè)務邏輯上的C/S 模式并非物理的 C/S 模式。進入整理,看文件 admin/global.php
/*用戶登錄*/ if ($_POST[loginname] && $_POST[loginpwd]) { //省略省略 login_logs($_POST[loginname], "成功登錄,保密了"); $_COOKIE[Admin] = "$rs[uid] ".mymd5($rs[password]); setcookie("Admin", $_COOKIE[Admin], 0, "/"); } if ($ForceEnter == 1){ $groupdb = @include(ROOT_PATH."data/group/3.php"); $Apower = ($groupdb[allowadmindb]); }elseif(!$userdb){ include "./template/login.htm"; exit; } else{ //同步前臺登錄 $md5code = mymd5("$lfjdb[uid] $lfjdb[username] $lfjdb[password]", "E N", $onlineip); } setcookie("adminID", $md5code, $timestamp + 1800, "/"); }
在驗證登錄的后,多次使用了 HMAC 算法對 cookie 進行加密典型的有 $_COOKIE[adminID]和$_COOKIE[admin]。
再看文件 inc/function.inc.php
//同步后臺登錄 if ($_COOKIE["adminID"] && $detail = mymd5($_COOKIE["adminID"], "DE", $onlin eip)){ unset($_uid, $_username, $_password); list($_uid, $_username, $_password) = explode(" ", $detail); $lfjdb = $db->get_one("SELECT * FROM {$pre}memberdata WHERE uid="$ _uid" AND username="$_username""); }
由上文可知 $_COOKIE[adminID]的明文形式是
uid username password
三個參數(shù)由 tab 分割。
那么 list($_uid, $_username, $_password) = explode(" ", $detail); 之后就把結(jié)果保存到 $_uid , $_username 和 $_password如果前后參數(shù)個數(shù)不同,那么 那個參數(shù)就會為空。
下面進行查庫
$lfjdb = $db->get_one("SELECT * FROM {$pre}memberdata WHERE uid="$_uid" AND username="$_username"");
如果我們構(gòu)造 uid = “1’#”那么查詢語句實際就變成了 SELECT * FROM {$pre}memberdata WHERE uid=1滿足條件,前臺登錄成功,前臺登錄認證就這一出。
由于 COOKIE 采用了密文交換,那么我們就不用關(guān)心 單引號被轉(zhuǎn)移的問題,真是太棒了,當然這個 uid 一定要存在,一般創(chuàng)始人 uid 基本=1結(jié)合上文,我們只要構(gòu)造出一個解密后的 COOKIE[adminID] = “1’#”即可。那么根據(jù)暴力分析一章,我們要構(gòu)造的 EncryptData 長度為 3范圍 000~fff總計 16^3=4096 規(guī)模,相當可觀。
計算出 hashcode 為 cdb8c28d5d
ps:md5(1’#) =a425ef44cdb8c28d5d434b2a1343205e
那么我們只要枚舉 base64_encode( 000~fff) + cdb8c28d5d。
最重要的一點我們發(fā)現(xiàn)在認證登錄的時候傳入了$onlineip 變量,可能導致 key 變動,不能暴力,看代碼 inc/function.inc.php
if ($_SERVER["HTTP_CLIENT_IP"]){ $onlineip = $_SERVER["HTTP_CLIENT_IP"]; }elseif($_SERVER["HTTP_X_FORWARDED_FOR"]){ } else{ } $onlineip = $_SERVER["HTTP_X_FORWARDED_FOR"]; $onlineip = $_SERVER["REMOTE_ADDR"];
那么我們直接構(gòu)造固定的HTTP_X_FORWARDED_FOR 參數(shù)即可。
并且 http 請求提交登錄認證頁面,并根據(jù)返回值判斷。
其實前臺可以直接getshell不過不在我們討論范圍內(nèi)。
最后 ending…如有不足請指點,亦可留言或聯(lián)系 fobcrackgp@163.com.
本文為篤行原創(chuàng)文章首發(fā)于大題小作,永久鏈接:齊博CMS:HMAC+COOkie注入漏洞分析
https://www.ifobnn.com/qibocmshmac.html
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/30648.html
摘要:原理分析還是很早之前爆出來的漏洞,現(xiàn)在拿出來學習一下,參考阿里巴巴漏洞發(fā)生在頁面中。并且與此同時,齊博并未對進行過濾操作。漏洞利用這里還是以文件中的變量為例。 ** 0x01 原理分析 **還是很早之前爆出來的漏洞,現(xiàn)在拿出來學習一下,參考阿里巴巴:https://security.alibaba.com/...漏洞發(fā)生在/inc/common.inc.php頁面中。首先看這個函數(shù):s...
閱讀 1008·2021-09-30 09:58
閱讀 2838·2021-09-09 11:55
閱讀 2004·2021-09-01 11:41
閱讀 996·2019-08-30 15:55
閱讀 3356·2019-08-30 12:50
閱讀 3500·2019-08-29 18:37
閱讀 3297·2019-08-29 16:37
閱讀 2018·2019-08-29 13:00