瑞友天翼应用虚拟化系统远程代码执行漏洞原理分析
2023-04-13 14:23:00

0x00、前言

核心由SQL注入引起的RCE,在没思考SQL注入之前,单看漏洞描述(远程代码执行),前后对比新旧版本看了老半天也没发现修改的哪处代码有代码执行,后面通过一些通报预警描述的由于SQL注入引起的才明白过来,算是分析走的坑吧。还是记录分析过程,文章偏向过程分析的思路和思考。(由于poc暂未公开,测试poc以打码处理,针对分析的漏洞点仅存在于漏洞版本内,最新版7.0.3不受下文分析点影响)

0x01、应用描述

瑞友天翼应用虚拟化系统(GWT System)是国内具有自主知识产权的应用虚拟化平台,是基于服务器计算(Server-based Computing)的应用虚拟化平台。它将用户所有应用软件(ERP、OA、CRM、PDM、CAD……)集中部署在天翼服务器(群)上,客户端通过WEB即可快速安全的访问经服务器上授权的应用软件,实现集中应用、远程接入、协同办公等,从而为用户打造集中、便捷、安全、高效的虚拟化支撑平台。操作终端无需再安装应用程序,通过天翼独特的RAP 协议(Remote Application Protocol),即可让用户快速访问服务器上的各类应用软件;天翼RAP 协议只传输鼠标、键盘及屏幕变化的矢量数据,访问仅需3KB/s(20kbps)的带宽,用户不再受客户端和连接性能要求的限制,在任何时间、任何地点,利用任何设备、任何网络连接方式,即可高效安全地访问服务器(群)上的应用程序和关键资源。

0x02、漏洞描述

瑞友天翼应用虚拟化系统存在远程代码执行漏洞,未经身份认证的远程攻击者可以利用该漏洞在目标系统上执行任意代码。

0x03、漏洞范围

5.x <= 瑞友天翼应用虚拟化系统 <= 7.0.2.1

0x04、环境搭建

下载的漏洞版本安全性未知,就不贴出来了,安装包是个集成环境,自带了php、mysql环境,下载安装包一键式安装起来就行

默认路径:C:\Program Files (x86)\RealFriend\Rap Server\

0x05、漏洞复现


0x06、原理分析

分析思路踩坑:
(记录下分析过程的一些坑点,对分析成长还是会有帮助)
系统的目录结构:

其中7版本以上都用了tp框架,根目录下的主要文件都是XGI后缀格式,使用Php编译访问,官网下载的7版本已经解密,互联网下载的6版本还是加密需要zend解密

查看更新补丁情况

更改了大部分的文件的部分内容,但大多都是增删代码的操作,看完并未找到修复远程代码的核心代码,也没找到直接触发远程代码执行的漏洞,直到看到有厂商漏洞通报的漏洞描述写的由SQL注入导致的RCE,这才把关注点转移到SQL注入上。(踩坑一)

在去发现SQL漏洞点的过程中,先是比较了新版本修复的代码,发现未对用户输入的参数之类进行修复过滤,也就是说分析思路从新旧版本的修复代码对比上,无法直接看出漏洞点。(踩坑二)


正式分析:
系统中采用了大量的SQL查询,并且很多地方都没有进行过滤并且参数可控(分析思路:找到SQL执行点,追溯可控变量,根据判断条件构造代码)

找到存在SQL执行,变量可控的点,示例点:

一类是直接在类中进行调用,只需要追溯满足调用条件即可,如下:

一类是在方法中进行调用,需要追溯在哪些类中调用了该方法,并满足调用条件,如下:

分析以这两类举例分析漏洞点,该系统还有好些点存在SQL注入,能达到同样的效果,就不赘述

定位到sql注入点(文件:ConsoleExternalUploadApi.XGI)

其中$adminName变量和$adminPwd变量都是由上面$requestObj数组中得来,$requestObj数组由$paramArr数组分割”_”符号循环取值,而$paramArr数组由$initparams变量分割”__”符号进行循环取值

$initparams数组由用户传参传递进来

理逻辑就是:例如$initparams="a_1__b_2__c_3",则$paramArr数组读取分割”__”符号,取值则为$paramArr[0]=a_1$paramArr[1]=b_2$paramArr[2]=c_3,其中$requestObj$paramArr数组变量分割”_“进行循环取值,则$requestObj['a']=1$requestObj['b']=2这个逻辑。

$initparams变量知道构造格式了,接着看触发sql执行前面需要满足的其他条件

断点是需要满足的条件:

  • keysigninitparams存在且不能为空
  • $keyVal必须存在且不为空,通过getfarminfo( $key )获取

其中key为查询farm表中是否存在名为key变量值对应数据库的值,意思key变量必须为数据库中存在的name值,取对应的数据库值给$keyVal变量


  • $initparams.$keyVal变量拼接的md5值需要等于$sign变量

上面的条件则为payload参数的必要条件,其中initParamskeysignkeysign已经知道了需要构造的数值,剩下initParams变量,只知道构造格式,还不知道需要具体格式构造的字符串,接着看执行sql前对initParams变量的操作

需要满足:$initParams=command_xx__user_xx__pwd_xx__serverIdStr_xx,来满足取值

其中需要满足command字段等于(uploadAuthorizeKeyFile|uploadFileToMenu|uploadFileToMenuDo|delAppFile|uploadIcon)这几个值之一。并且userpwd存在且不为空即可

接着$adminName$adminPwd字段存在SQL注入,就能执行sql注入达到rce的目的了


上述的触发方式每一步payload构造都需要计算sign值,通过$initparams变量和$keyVal拼接再进行md5计算,调试或者跑sqlmap都需要更改脚本添加md5加密操作。

$signCalculate = md5( $initparams.$keyVal );

同文件还有一个触发点(也就是上述中的sql注入调用方法的情况):

这里的步骤在最开始当initParamskeysign存在且不为空即可执行到该步骤方法

此时的key即调用方法传入的name变量,直接进行sql执行,达到sql注入的目的,就不需要第一种方法中的计算md5、构造$initparams参数等操作



此外提及的执行Sql知道的物理路径:

  • 默认安装在C:\Program Files (x86)\RealFriend\Rap Server\
  • 7版本可通过tp框架报错查看路径,默认开启了debug调试

0x07、漏洞修复

官方已经推出更新补丁升级至7.0.3.1
http://soft.realor.cn:88/Gwt7.0.3.1.exe

(从代码层面没看出来做了什么代码安全过滤)

0x08、参考链接

https://mp.weixin.qq.com/s/ZZYWISRS7D1YqJE9S3h7bw
http://www.realor.cn/product/xiazaishiyong/