环境搭建:
搭建参考:https://wiki.smartbi.com.cn/pages/viewpage.action?pageId=114987452
访问 http://ip:18080/smartbi/vision/index.jsp
漏洞分析:
下载漏洞补丁:
https://www.smartbi.com.cn/patchinfo
使用如下脚本解密,得到压缩文件后解压
1 | import argparse |
查看 patch.patchs 补丁文件,根据漏洞描述猜测权限绕过发生在 /vision/share.jsp 文件中


继续跟进,只需要满足条件 shareService.isPublicShareResourceByShareType(resid, sharetype),并且让 JSONObject result = shareService.getShareRestrictByShareType(resid, sharetype) 的结果为 false 就可以直接调用 UserManagerModule.getInstance().autoLoginByPublicUser() 来获取合法Session。
/smartbi/vision/share.jsp
继续跟进 shareService.isPublicShareResourceByShareType(resid, sharetype),满足根据 relateid (也就是resid) 查询到的 shareRecord 不为空且 Publicshared 为1就会返回 true
smartbi.module.socialcontactshare.SocialContactShareService#isPublicShareResourceByShareType
在 smartbi 数据库 t_share_record 表中查询两个满足条件的 relateid 值:96a0a9d0b86f90d5416d013f4cfe2f23 和 b904ab9f5a84712a672523a7b4881ee4

继续跟进 shareService.getShareRestrictByShareType(resid, sharetype),当 shareType 为空就调用 this.shareRestrict(relateid, (String)null, (String)null, (String)null)
smartbi.module.socialcontactshare.SocialContactShareService#getShareRestrictByShareType
在 shareRestrict() 方法的条件判断中 shareRecord.getCode() 获取数据库 t_share_record 表中的值为空,所以最终返回false。
smartbi.module.socialcontactshare.SocialContactShareService#shareRestrict
最终使用以下http请求获得合法 public 用户 Session
1 | GET /smartbi/vision/share.jsp?resid=b904ab9f5a84712a672523a7b4881ee4 HTTP/1.1 |
在 patch.patchs 6月份的补丁中搜索到了一个明显的关键字

搜索相关方法,可以看到不需要admin权限,并直接调用js引擎执行了传入的表达式。

而 Smartbi 的smartbi.framework.rmi.RMIServlet 可以通过 smartbi.framework.rmi.ClientService#executeInternal 反射调用任何方法,不再赘述。
漏洞复现:


