1. 程式人生 > >XerCMS-1.0.3代碼審計(文件名報錯註入後臺getshell)

XerCMS-1.0.3代碼審計(文件名報錯註入後臺getshell)

each orb his jpg pla module 將不 last self

鏈接:https://share.weiyun.com/6b98e41d036967178e1a21fb88ed340f (密碼:YnNY)

文件名報錯註入

index.php?m=member&a=upfiles&id=2

在這個文件夾中XerCMS\Modules\member\index.php

前臺註冊個用戶 在頭像上傳處抓包reperter一下用mysql監控工具

技術分享

發現有insert數據庫操作 分析一下

跟進upfiles函數

   public function upfiles() {
          setformat(‘json‘);
          $config
= ini(‘member/group/‘.X::$G[‘group‘]); if(empty($config)) { exit(‘Access Denied‘); } else { if($config[‘upload‘][0] == 0) { error(‘upload_group_limit‘); } else if($config[‘upload‘][1] != 0 && X::$G[‘upload‘] > $config
[‘upload‘][1]) { error(‘upload_group_size‘); } } $id = int1(g(‘id‘)); c(‘upload‘)->load($id); $image = ini(‘image‘); if(isset($image[‘status‘]{2})) { c(‘upload‘)->config[‘thumbs‘] = array(array
(‘width‘=>$image[‘width‘],‘height‘=>$image[‘height‘],‘cut‘=>$image[‘cut‘],‘quality‘=>$image[‘quality‘])); } else { if(isset(c(‘upload‘)->config[‘thumbs‘])) unset(c(‘upload‘)->config[‘thumbs‘]); } c(‘upload‘)->files(); c(‘upload‘)->show(); }

通過c(‘upload‘)->files()完成上傳操作

跟進一下files函數/XerCMS/Library/XerCMS_upload.php

    function files() {
            foreach($_FILES as $k=>$v) {    
            $this->file($k);
        }
    }

繼續跟進file函數

    function file($name) { 
        if(isset($_FILES[$name][‘tmp_name‘]) && !empty($_FILES[$name][‘tmp_name‘])) {
            $ext = $this->ext($_FILES[$name][‘name‘]);
               if(in_array(strtolower($ext),$this->forbid) || preg_match(‘/([^a-z0-9])/i‘,$ext,$match)) {        
                    $this->result[$name][‘error‘] = ‘Ext‘;return;
               }    
            if(!empty($this->config[‘maxsize‘]) && $_FILES[$name][‘size‘] > $this->config[‘maxsize‘]) {
                $this->result[$name][‘error‘] = ‘Size‘;return;
            }
              $rid = $this->record($_FILES[$name]);
            $this->dir($this->config[‘path‘],$rid,$ext);
            if(is_uploaded_file($_FILES[$name][‘tmp_name‘])) {
                    if(move_uploaded_file($_FILES[$name][‘tmp_name‘],$this->name($rid)) == false) {
                         $this->delrid($rid);
                         $this->result[$name][‘error‘] = ‘Move‘;return;
                    } else {
                     //chmod($this->name($rid),0644);
                }
                if($this->config[‘local‘] == ‘0‘) {
                        if(!REMOTE::upload($this->name($rid),$this->name($rid),$this->config[‘remote‘],$this->config[‘mode‘])) {
                             $this->delrid($rid);@unlink($this->name($rid));
                             $this->result[$name][‘error‘] = $this->config[‘mode‘];return;
                        }
                   }
                //if($helper != null) {
                    $files = $this->handle($this->name($rid),$ext);    
                    if($files != null && $this->config[‘local‘] == ‘0‘) {
                         foreach($files as $file) {
                                if(!REMOTE::upload($file,$file,$this->config[‘remote‘],$this->config[‘mode‘])) {
                                     $this->delrid($rid);
                                     $this->result[$name][‘error‘] = ‘extra‘;    
                                break;
                                }                        
                        }
                        if(!empty($this->result[$name][‘error‘])) {
                             foreach($files as $file) {
                                 @unlink($file);
                            }
                             return;
                        }
                    }
                //}    
               }
            $this->result[$name][‘host‘] = $this->config[‘host‘];
               $this->result[$name][‘path‘] = $this->name($rid);
               $this->setPath($rid,$this->result[$name][‘path‘]);
        } else $this->result[$name][‘error‘] = ‘Tmp‘;
    }
var $forbid = array(‘php‘,‘asp‘,‘aspx‘,‘vbs‘,‘bat‘,‘asa‘);

後綴利用的是黑名單 可以進行php3 php5 繞過 這裏不是重點

繼續跟進一個record函數

     function record($upfile) {
        if (X::$G[‘uid‘]) {
               DB::add(‘xercms_member_count‘,array(‘upload‘=>$upfile[‘size‘]),array(‘uid‘=>X::$G[‘uid‘]));
        }
          DB::insert(‘xercms_member_upfiles‘,
             array(‘uid‘=>X::$G[‘uid‘],
                ‘size‘=>$upfile[‘size‘],
                ‘name‘=>$upfile[‘name‘],
                ‘time‘=>X::$G[‘time‘],
                ‘ip‘=>X::$G[‘ip‘],
                ‘type‘=>$this->cid));
          return DB::lastid(); 
     }

可以看出有個insert操作

而前面的函數傳參是文件本來的文件名

 $rid = $this->record($_FILES[$name]);

而且這套cms並沒有進行全局過濾

所以導致了註入

static function insert($table,$fields) {
     if (empty ($fields)) {
          return ;
     }
     foreach ($fields as $k=>$v) {
          $content[] = ‘`‘ .DB::filter($k, ‘f‘ ).‘` = \‘‘.DB:: filter($v).‘\‘‘ ;
     }
     self ::query( ‘INSERT INTO ‘ .$table.‘ SET ‘.implode( ‘,‘,$content), self ::$connect );
     return self ::lastid();
}

其中filter函數還有一點過濾

    static function filter($str,$t = ‘‘) {
        $str = (string)$str;
        switch($t) {
            case ‘f‘:
                return preg_replace(‘/([^a-z0-9_])/i‘,‘‘,$str);
              break;
              default:
                    return trim($str,‘\\‘);
              break;
        }
      }

針對key 將不是字母和數字還有下劃線的其他字符替換成了‘‘,而對value只是過濾了\,所以是可以造成註入的,接下來跟進query方法

技術分享

開啟了報錯 導致了可以報錯註入

技術分享

技術分享

文件名1‘ or updatexml(1,concat(0x7e,(version())),0) or ‘.jpg" 看返回

XerCMS-1.0.3代碼審計(文件名報錯註入後臺getshell)