0x00 背景
五月份给 CNVD 提了个洞,Smartbi 在今天修了,记录下当时挖洞的过程。
2023-07-03 修复登录代码逻辑漏洞。
0x01 漏洞分析
Smartbi 针对 RMIServlet 的防护主要是通过 CheckIsLoggedFilter 完成的,整体的校验逻辑为:
- 获取 className、methodName、params
- 校验上述参数,判断是否符合预期(在白名单内)
Smartbi 会尝试通过多种方式获取并解析这三个参数,下面是解析顺序(上一个解析失败则向下顺延):
通过 windowUnloading 进行解析
通过 request.getParameter 进行解析
通过 request body 解析
通过 encode 参数解析
其中任何一个步骤解析成功了,都不会进行下一个步骤。接下来看看 RMIServlet 是怎么解析的:
这里一共只有三步:
- 通过 request.getParameter 解析
- 通过文件上传的格式去解析
- 通过 request.getAttribute 解析
从解析流程中不难看出这里存在一个差异绕过的问题,第一步使用 windowUnloading 对参数进行设置,同时在请求的参数里也进行设置,那么在 CheckIsLoggedFilter 里拿到的就是 windowUnloading 里的参数,而 RMIServlet 拿到的却是请求里的参数。
构造 POC:
1 | POST /smartbi/vision/RMIServlet?windowUnloading=className%3DUserService%26methodName%3DautoLoginByPublicUser%26params%3D%5B%5D HTTP/1.1 |
出现 PARAM_COUNT_ERROR 表明已经调用到了恶意 Bean:
0x02 补丁分析
Smartbi 新增了 WindowUnLoadingAndAttributeRule 规则来修补这个漏洞,它会先判断请求中是否存在 windowUnloading 参数,接着判断请求中是否存在 className 和 methodName 等参数,如果存在,则判断二者解析出来后是否相同。
漏洞修复后,返回包为 403: