As I have discussed capabilities in my previous post, there are 40 capabilities, but from an infosec point of view, I will discuss around 20 of them. Fitting writeup for all of them in one post in nearly one post is nearly impossible. I will discuss 4 labs in each post
In this post, I will discuss 2 capabilities related to setuid and setgid. If you want a refresher on them, I have written two posts – Demystifying SUID and SGID bits and Exploiting SUID Binaries to Get Root User Shell
Following are the name and links of the labs I will be discussing today
So let's start off with the first lab
LAB: The Basics: CAP_SETUID
To get the files with at least one capability, you can use getcap recursive search using
getcap -r <directory> 2> /dev/null. Redirecting stderr to /dev/null is quite convenient as if the file doesn't have any capability or reading capability is not allowed, it will throw the error
Since python interpreter has cap_setuid allowed in the effective set, this means any it can arbitrarily set the user id, even though the user-id is set to 0, you can't set the group id because the process is not running with EUID = 0 and cap_setgid is not allowed. So kernel will drop the action and you will get an "Operation not permitted" error
You can find the reference of same on hacktricks gitbook – https://book.hacktricks.xyz/linux-unix/privilege-escalation/linux-capabilities#cap_setuid
LAB: The Basics: CAP_SETUID II
While finding the capabilities recursively in the root directory, I found that again python2 interpreter has cap_setuid set
If you look closely, this time it is in the permitted set. So if you try setting UID to 0, where it will fail will be the "Operation not permitted" error. This actually makes sense as the kernel will look for the capabilities in the effective set rather than the permitted set.
However, you can fix this by importing prctl and then transitioning the capability from permitted to effective set. Once this is executed successfully, call
os.setuid(0) and this time it will be executed successfully
In case the capabilities are in the permitted set and prctl is not installed, you can import the ctypes module, load libc and call the prtcl function from that
LAB: The Basics: CAP_SETGID
On getting capabilities recursively in the root directory, I found that this time python interpreter has cap_setgid capability set to both effective and permitted set.
When a program has cap_setgid capability set in the effective set, you can arbitrarily change the group id when the program is executed. This will not allow you to change the user id.
You can not directly spawn the privileged shell, but perform group-specific action on the files having the same group id as of your current running process, after you call os.setgid() function. This will call setgid() syscall under the hood
In the description, it is written that the flag is the hash of the root user. Since there is no write permission to the group in these files, getting a privileged shell is not possible but you can read the content of the shadow file. Since the setgid function require a group id, you can find this information in the /etc/group file
Now I have everything to proceed with, it's time to change the group id to 42 and read the first line from the /etc/shadow file.
When you open the file in python using the open built-in function, it will give you an iterator, to read the first line simply type execute the
next(file) function by passing variable to filehandle
So in this case, the hash will start from
Yg .... 1. Remember, $1$ is the hash type and $flag$ is the salt, not hash value
For more reference, you can refer to the hacktricks gitbook – https://book.hacktricks.xyz/linux-unix/privilege-escalation/linux-capabilities#cap_setgid
LAB: The Basics: CAP_SETGID II
On checking capabilities recursively in the root directory, I found that again the python interpreter was allowed to change the group id.
The flag this time is in the home directory of the root user (i.e /root) but I can't perform any action in the /root directory either ways
I found that the current system is running the docker service as the docker socket exists in the /var/run directory and docker CLI is also installed. This means if anyhow I can get run docker container, I can then take over the system
I found the docker group can perform read and write actions on the docker socket thus sending commands to the docker service. This isn't a misconfiguration but you can see how running an unintentional application and having another binary to change gid can be a vulnerable vector
Let's test all these by listing docker images. If there is no image, it would be then again impossible to escalate to the root user.
Use the /etc/group file to find the group id of docker and spawn a shell from python by setting gid same as of docker.
Since the docker has an ubuntu image, it is pretty obvious that it will provide a shell to execute commands. Use docker to mount the root in /host directory of the container and spawn a shell. Later you can use chroot utility to get into the root file system of host and perform actions via root user
If you are looking for a refresher on how to use chroot, I have already written a post on it – Breaking out of CHROOT Jailed Shell Environment