SmartBi 未授权远程代码执行
前言
今年七月份的时候SmartBi爆出来一个未授权rce,我就分析了一波,然后跟着继续挖了一下,挖到一些授权的xxe注入和后台rce,紧接着七月底又爆出一个获取token的洞,赶紧去分析了一波看看对补丁有没有办法绕过,果然找到了绕补丁的方法,结合着原来挖到的后台rce,两个洞结合可以未授权rce
漏洞分析
权限绕过
是在MonitorService
类中
在smartbix.datamining.service.MonitorService#setEngineAddress
中,配置不需要权限,即可访问,在该函数中,可以设置Engine的地址
然后在同一类中的getToken函数中,获取token放入请求包,向前面设置的Engine的地址发送请求包,请求路径为:/api/v1/configs/engine/smartbitoken
,如果返回json格式的返回包,会返回true
拿到token后在通过,同一类中的loginByToken函数即可获取JSESSIONID
利用方式就是,构造一个假的Engine地址,可以接收token,再去获取JSESSIONID即可
具体怎么利用就不细说了,如下图所示,返回包返回true说明JSESSIONID可以拿着去登录后台了
官方的修复方式是:对setEngineAddress路由加了权限校验
另一个权限绕过
在MonitorService
类中,和上一个权限绕过类似使用了另一个路由,通过另一个路由触发setEngineAddress路由修改地址
在smartbix.datamining.service.MonitorService#setAddress
中,我们传进去的address为des加密过的json字符串,进入后先解密然后转换为ObjectNode可以理解为就是json字符串,接着往下走,判断obj中是否有c_address字段,然后判断type字段的值是否为experiment,最后取c_address字段的value,和EngineApi.address("engine-address")
对比,一样的话进入到setEngineAddress路由中,且值为u_address字段的value,这里默认的engine-address
地址为:http://localhost:8899
然后可以通过CommonUtil类进行des加密
设置成功,后续和上次权限绕过一致
后台rce
该漏洞为JDBC 进行的JNDI注入 入口点是在SyncServlet中,type为sqldictsync时进入分支
进入smartbi.freequery.sync.SyncResources#synchronize()
中,基本确定为JDBC连接,就看后续有没有对参数的限制和具体连接方式了
进入到smartbi.util.DbUtil#getConnection()
中,url参数是从drvInfo中取值的,跟进到translateDriverInfo
中
smartbi.util.DbUtil#translateDriverInfo()
中,就是通过传进来的dbType确定数据库和驱动,这里还是使用DB2进行JNDI注入,这里红框内是最终拼接而成的url,这里有个我踩坑的地方就是dbName后还拼接了:deferPrepares=false;
(这个参数就是在执行sql语句前进行预编译),没注意到:
,导致后面进行jndi注入时可以接收到jndi请求,但是一直没打成功,还是要细心点,直接在dbName最后加个;
即可
最后进入到smartbi.connectionpool.ConnectionPool#getConnection()
中,进行了对JNDI注入的验证,第一个if条件是判断url里是否有:clientrerouteserverlistjndiname=
有的话就抛出异常,这里直接使用a:a=a;clientRerouteServerListJNDIName=
绕过即可,第二个检验url开头是否为JNDI:
还有java:
的校验,不了解这是在防御什么,反正没什么影响,接着就直接进行连接了
最后两个洞结合即可