0x00 背景
Smartbi 在 2023-06-12 日修复了一处安全漏洞:
2023-06-12 修复在某种特定情况下默认用户绕过登录漏洞。
0x01 漏洞分析
这个漏洞在今年早些时候因为一些原因挖到了,核心问题在于 Smartbi 在安装时内置了几个服务账号,通过特殊的接口可以登陆这些账号,从而获取一个登陆态的 session。
Smartbi 安装后默认无法登陆内置的 MySQL 数据库,需要使用一些魔法,登陆后查询 t_user 表可以发现除了 admin 和 public 用户外,还有几个内置账户(public、service、system)也在表中:
如果你尝试直接使用这几个账号在前台登陆,会发现其实是无法登陆的:
这是因为正常登陆走的是 SecurityServiceImpl#loginDB
方法的逻辑:
这里通过 UserBO#isPasswordValidate
来判断表单输入的密码是否和用户真实密码一致:
当用户的密码以0开头时,会先将表单密码进行 MD5 处理后再和数据库里的密码进行对比,因为没有一个字符串在经过 MD5 处理之后是 0e
,所以无法通过常规接口登陆。
反编译搜了一圈之后,发现可以利用 UserService#loginFromDB
通过明文密码登陆:
这里从数据库取出用户密码后直接和没有经过任何处理的 password 进行比较,如果两值相等则通过 StateModule#setCurrentUser 给当前 session 设置了登陆态,最终实现登陆绕过。
以 service 用户为例,发出如下请求即可获得包含 service 用户身份的 session:
1 | POST /smartbi/vision/RMIServlet HTTP/1.1 |
如果登陆失败,则响应中的 result 为 false:
登陆了之后可以干什么呢?实际上 Smartbi 对于 RMIServlet 远程代码执行的修复方式仅仅是判断用户是否登陆,因此登陆后依然可以使用 RMIServlet 结合 JDBC 实现任意代码执行或任意文件写入。
0x02 补丁分析
下载了 Smartbi 的补丁并对其进行解包后发现 Smartbi 对这个漏洞进行修复的方式简单粗暴,当 url 为 /vision/RMIServlet
并且 className 和 methoName 为 loginFromDB 时直接 Reject。