通达 v11.8前台文件上传&命令执行漏洞利用分析

通达 v11.8前台文件上传&命令执行漏洞利用分析

1537871692507722 白帽子左一 2023-12-16 12:01

扫码领资料

获网安教程

免费&进群

api.ali.php任意文件上传

影响版本

v11.8

漏洞复现过程:

漏洞原理是通过文件上传上传一个json文件,再通过调用程序去解析json文件执行里面php语句

首先需要上传一个json文件

完整数据包:

接着发送get请求写入文件,成功在webroot目录下写入fb6790f4.php,2109为年月份

分析过程

文件上传功能实现的地方在mobile/api/api.ali.php文件下

其中包含了conn.php、api.api.class.php、utility_file.php三个文件,这三个文件都是负责加载通达的配置信息以及通用函数,不涉及权限验证

跟进到utility_file.php下的upload()

$ATTACH_NAME = filename_valid($ATTACH_NAME); $ATTACH_NAME的值是上传时的文件名

接着会判断上传的文件后缀是否是允许的,限制了php,php3,php5等文件后缀,以及文件名是否合法,当没有错误后会进入到1761行中

跟进add_attach(),系统会将我们上传的文件保存在attach/approve_center/2301文件夹下面,其中2301是上传的年月份

文件名$FILENAME由$ATTACH_ID和$ATTACH_FILE两部分组成,$ATTACH_ID是随机生成一串数字,通过跟进发现MYOA_ATTACH_NAME_FORMAT恒为false,所以最终的文件名为 随机数字+上传文件名

通过这个功能可以上传一个除可执行文件外的文本文件到服务器上

触发生成php文件的功能点代码文件在/inc/package/work.php下,也没有做鉴权操作

接收了一个id参数,进入到DataTransport类下的acceptData(),程序首先将用户传入的id拼接到文件路径里,接着执行file_get_contents()读取$json_file所指向的文件

MYOA_ATTACH_PATH2的值为myoa/attach,问题在于$id在路径中做了两次拼接,程序没有对../进行过滤,而且经过上面的分析我们知道上传到服务器上的文件名都带有一串9位数的随机数字,我们没有得到准确的文件名

在linux下可以通过、?这一类的通配符来匹配文件名,例如/etc/passwd可以用/etc/pass*来匹配成功的,在file_get_contents()里也可以用<,>来实现,用’<<<<<<<<<<’来匹配随机生成的9位数随机数

file_get_contents()读取文件时,存在一些特殊的特性,在d盘data文件夹下创建test.txt文件用来测试,使用file_get_contents()进行文件读取

这三种FilePath的形式到最后都能成功读取到data/test.txt文件,只要最后一个../后面是正确的路径地址,file_get_contents()都能成功读取到文件。

其中还有一个关键部分,就是跨目录层数要大于等于目录层数

第一种写法是无法读取到test.txt文件的,第二种是可以的,可以根据这两种之间的区别去理解

现在已经可以解决关于json_file文件读取的问题了,接着在work.php中传入id的参数为

程序读取完json文件后,执行到AllVariableBusinessProcessing类的backDataAnalysis()

该方法下存在eval函数可以执行代码,而且$variableData的值是可控的

至于dataAnalysis为什么是这种格式,下面会详细讲到,这里先给出一个demo

在上面的代码中,定义了两个数组a和b,执行过后就能看到程序输出了1234,这说明$b中的php语句成功执行了。所有只要用户能控制$b[a]的值,令$b[a]=’b’,eval(base64_decode($c)));/*’,闭合掉前面的单引号那就可以执行恶意的php语句了

但是当调用work.php读取json文件的内容到$variableData时会对其中的单引号进行转义,php代码要执行成功,就必须将单引号逃逸出来与前面的单引号进行闭合

所幸主角iconv出来救场了。iconv在这里的作用是将$variableData从UTF-8编码转换成GBK编码,其中錦的UTF-8编码是\xE9\x8C\xA6,GBK编码是\xB0\xA1,当编码转换之后\xB0\xA1会和\组成一个新的字符,单引号就成功逃逸出来了

getdata任意命令执行

在v11.8版本下还存在一个前台任意命令执行漏洞,该漏洞的漏洞利用方法和上面的类似

漏洞代码在general/appbuilder目录下,而且是MVC的架构,首先看web/index.php文件,判断config[“params”][“LOGIN_UID”]是否为空,跟进config/web.php文件可以看到config[“params”][“LOGIN_UID”]=””

继续向下执行会判断是否存在相应LOGIN_UID的session,我们在未登录的情况下是不存在的,所以会进入到下面的else语句

通过分析代码,可以知道/portal/gateway/**下的路由只有/potal/gateway/saveportal是需要鉴权的,所以这是一个前台的RCE

根据漏洞的poc最终找到漏洞文件在modules/portal/controllers/GatewayController.php,用户传入的module=Carouselimage,程序执行到2016行进入到$component->GetDate(),传入的参数里有$activeTab,也就是需要执行的命令

跟进到modules/portal/models/PortalComponent.php#GetData(),系统通过id查询数据库中的内容,$comtype在后续会使用到,要令$comtype=1

$comtype = (string) $data->comtype;

从数据库的查询结果可以看到,只要我们令id=19就能控制comtype=1

接着将id,comtype,attribute存在$this_array里,接着进入到data_analysis()

/portal/components/AppDesignComponents.php#data_analysis(),$classname=Carouselimage,当$thisarray[“comtype”] == “1”时,执行到free_components/AppCarouselimage.php#get_data()

从Gateway控制器下到AppCarouselimage.php#get_data()都没有对$activeTab进行处理和过滤,

回到gateway控制器下,执行完$component->GetData()后会返回一个带有$activeTab参数的数组

跟进toUtf8(),程序通过eval执行我们的命令,这里也使用到了iconv,所以payload构造原理和上面分析的一样

来源: https://xz.aliyun.com/t/13175

声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权

@
学习更多渗透技能!体验靶场实战练习