0x00、前言
泛微Ecology(CheckServer-SQL注入)漏洞复现与分析,针对CheckServer.jsp的漏洞点的复现和分析,本来是复现分析任意用户登录的漏洞,安装下载折腾了半天然后发现安装的版本不存在该漏洞,借此转向前端时间的SQL注入漏洞,brower-sql注入的后面再补。
0x01、漏洞描述
泛微 Ecology OA 系统对用户传入的数据过滤处理不当,导致存在 SQL 注入漏洞,未经过身份认证的远程攻击者可利用此漏洞执行任意SQL指令,从而窃取数据库敏感信息。
0x02、漏洞范围
泛微 Ecology <= v10.56
0x03、环境搭建
这里下载的网上的泛微Ecology9版本,安装步骤可参考
http://www.taodudu.cc/news/show-5203830.html?action=onClick
https://blog.csdn.net/qq_35086986/article/details/129853901
步骤不再赘述,记下安装坑点,浪费了不少时间
由于安装环境的数据库是mysql,导致初始化数据库的时候报错了很多次
防止安装初始化数据库失败,需要修改mysql配置(本地数据库版本为Mysql5.7.24),步骤如下:
- 新建数据库名ecology,与初始化数据库名相同即可,然后需要设置utf-8编码
修改mysql.ini配置,在[mysqld]中新增内容
character-set-server=utf8 log_bin_trust_function_creators=1 lower_case_table_names = 1 sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES transaction_isolation = READ-COMMITTED group_concat_max_len = 102400 //修改默认存储引擎为InnoDB default-storage-engine=InnoDB
修改后重启mysql服务,然后再点击步骤中的初始化数据库,出现success即初始化成功,安装完成,即可访问
调试部署:
配置文件/Resin/conf/resin.properties,添加idea的调试代码即可
将Ecology文件夹中的classbean文件(泛微Ecology编译好的class文件)导入idea,运行配置添加远程jvm即可
发包即可抓包获取调试
0x04、漏洞复现
由于POC暂未直接公开,复现分析均以分析思路为主,执行payload进行打码处理。
0x05、原理分析
直接定位到有问题的CheckServer.jsp文件
通过FileUpload
类生成了一个request
请求的对象,可以调用request
用户请求的参数
再根据不同的type
值进行不同的处理方式
当type
等于checkPluginFile
时,获取fileHash
参数,并调用PluginServiceImpl.checkPluginFile
方法,跟进checkPluginFile
发现并没有相关的SQL执行操作
接着当type
等于mobileSetting
时,获取settings
参数和timestamp
参数,一起传入并调用PluginServiceImpl.syncMobileSetting
方法
接着跟进PluginServiceImpl.syncMobileSetting
方法,该方法先是从paramString1
参数(也就是传入的settings
参数)中读取json数据并转化为列表list,表明了settings
参数值必须满足Arrayjson格式,即[{"xx":"xx","xxx":"xxx"}]格式
,接着执行两个sql语句,不存在注入,然后判断list是否不存在或者为空
因此settings
参数必须赋值,赋值内容往下跟进看
接着创建list列表的迭代器循环读取list表中的元素,通过获取的元素可以知道settings
参数的json数据内容包括(scope、module、setting、modulename、include、orasc)六个元素,
当i
变量(也就是scope
参数)等于1|7|8|9|10时,操作内容都是向arrayList
数组列表添加数据
相关的添加完成过后,最后执行sql语句,也不存在sql注入
其中当i
变量(也就是scope
参数)等于2|3时,会调用saveMobileDocSetting
方法,其中传递的参数分别是(scope、setting、modulename)
接着跟进saveMobileDocSetting
方法,第一步进行判断,如果paramInt
参数(传入的scope)<= 0,或者paramString2
参数(传入的modulename)等于空的话,直接就返回了,因此条件必须满足scope>0,modulename不为空
接着判断paramString1
(setting)不为空的话,执行3处sql语句,该语句参数可控,但不存在SQL注入
接着就是重点的逻辑取值部分,先看前部分,也就是说当setting
值等于@xxx1#xxx2
时,bool判断为true
,并且去掉@
号进行重新赋值此时setting
值为xxx1#xxx2
,随后将#
作为分割符号,分割后xxx1
、xxx2
分别放入数组arrayOfString
再看后半段的逻辑取值,这里将前半段逻辑取值处理过后的arrayOfString
数据通过|
符号进行分割后重新放入新的数组arrayOfString1
,也就是当前面分割前如果setting
值为@xx|x1#xxx2
,通过前半段分割后变成xx|x1
和xxx2
,后半段再将|进行分割,将xx|x1
分割成xx
和x1
放入数组arrayOfString1
随后通过判断bool
变量值
如果为bool
值为true
也就是setting
值以@
为开头,则对arrayOfString1[0]
(也就是后半段逻辑取值中获取的xx|x1
中的xx
数据)进行url解码后赋值给str2
变量,最后执行SQL,此时SQL语句str2
可控,存在SQL注入。
若bool为fasle
,也就是setting
值不以@
为开头,例如xxx1#xxx2
,则直接将paramString2
值(传入的modulename
参数)赋值给str2
,然后执行SQL语句,此时str2
可控,理论上同前一种相同都存在SQL注入,将传入的paramString2
值构造成恶意的sql语句,也能实现注入,但实际测试发现传入的paramString2
值的字节被编码了导致语法错误,因此该参数不存在SQL注入
主体判断其他的type
判断分支思路同上,就不赘述了。
总结下条件:
- settings参数必须满足Arrayjson格式且存在
- scope>0,modulename不为空
- setting参数必须以@开头,并且存在#号进行分割,分割的前半段数据中需要存在|符号进行分割,|符号分割后的前半段需要经过URL编码一遍
- 最后将整体的请求setting参数再URL编码一遍,因为提交给服务器时会进行URL解码,如果只存在一次编码此时payload里面的字符会被解码出来导致执行失败。
0x06、漏洞修复
目前官方已发布安全补丁,建议受影响用户尽快升级至10.57及以上版本。
https://www.weaver.com.cn/cs/securityDownload.asp#
该漏洞官方补丁修复:
- 直接删除该文件代码(从源头解决问题)
0x07、参考链接
https://nox.qianxin.com/article/575
https://www.weaver.com.cn/cs/securityDownload.asp#