Cheese CTF
Inspired by the great cheese talk of THM! - by shadowabsorber and VainXploits
Last updated
Inspired by the great cheese talk of THM! - by shadowabsorber and VainXploits
Last updated
The following post by 0xb0b is licensed under CC BY 4.0
We start with a Nmap scan and find a lot of open ports. Including port 80 and 22.
In the hope of recognising services that are actually running, we use the version scan tag. But here too we are overwhelmed by the results.In order to identify those services that are actually operational, we employ the use of the version scan tag. However, even this approach yields an overwhelming number of results.
The next guess is simply to try it with a standard port like 80
. And we have a hit. A website, a Cheese Shop, that offers a login
as well as some products.
As a precaution, we run a directory scan using Feroxbuster to make sure we don't miss anything, but find nothing of interest that we don't already know about. The login
page.
On the login page, we try with default credentials, but cannot log in. We also notice that the error message is generic. Usernames and passwords cannot be derived.
We continue with the next possibility, SQL injection to bypass the login. Let's try something simple first and use SQLMap. To do this, we intercept the login request using Burp Suite and then use it in SQLMap.
We use the recorded request and follow the instructions in the interactive mode of SQLMap. Although we have no direct success, we can see that there is a redirect to /secret-script.php
. We were probably partially successful.
To get past the login, we use the procedure from the Injectics room and brute-force with a series of payloads.
We obtain the payloads from the following source and paste the content to login-bypass.md
:
It is important to note that this is a CTF, and we can use payloads without hesitation and without causing serious damage. In the following room, Tib3rius explains why it is important to rethink your actions and the choice of payloads - not using something like ' OR 1 = 1 -- -
:
With the following Fuff query, we get some results and choose the first one.
After we have transferred the following payload, we have successfully logged in.
In the admin dashboard, we can see that the resources are called up using the file parameter. This already indicates the first vulnerability of file inclusion. Furthermore, we see the use of php filters when integrating the resources. This gives hope for one of my favourite vulnerabilities. LFI2RCE via PHP Filters. A detailed write-up on this can be found here:
In short with that we are able to generate arbitrary php code for the include without needing to write it into a file. Which makes it really amazing.
We now try to include stump /etc/passwd
and are successful.
How such a payload can be generated with the help of a script can be found at PayloadAllTheThings:
The following source provides us with the script to build such a filter chain:
First, we keep it simple and generate a payload to display the phpinfo
page to see if filter chaining is possible.
We give the payload to the file parameter and see the phpinfo
page after loading the page. LFI2RCE via PHP filters seems to be possible.
Next, we generate a payload with the smallest possible PHP web shell.
We call the id command using the preceding parameter 0
. We are www-data
. We have remote code execution.
We now want to have a more interactive reverse shell. To do this, we spawn a reverse shell. We build a Bash -i
reverse shell using revshells.com
and encode it in base64.
To avoid possible conflicts with special characters in the URL, we encode it in base64 and execute it with the following command:
We set up a listener on our desired port and call up the page with our reverse shell command.
We get a connection back and use the opportunity to upgrade the reverse shell.
As www-data
, we cannot find the flag directly in its home directory. We first conveniently enumerate the target using Linpeas.
We realize that we can write to /etc/systemd/system/exploit.timer
. We keep this in mind for now, as it will only become important for us later.
We check out the home directories and see that we can read the home directory of the user comte
. This user has the first flag. We also notice that we can write to .ssh/authorised_keys
. Since we can write in authorized_keys
from user comte
, we have the option to write in our own public key, which allows us to access the machine via ssh with our private key as comte
. That's what we're doing now.
We create a new ssh key using ssh-keygen, change the permissions on the private key and copy the contents of the public key.
Now we just paste that into /home/comte/.ssh/authorized_keys
.
The next step is to log in as comte
with our private key...
... and have access to the first flag.
As comte
, we may execute some systemctl commands without adding a password using sudo. Here we see that it is the service exploit timer. This looks familiar to us.
Recalling the LinPeas result:
Let's take a look at what is behind the service /etc/systemd/system/exploit.service
. It copies xxd
to /opt
and turns it into a SUID
binary. Since it is then still in the possession of the root
user, we can use it to read any files.
We can find out how to exploit this at GTFOBins:
However, we receive an error message when we start the service. The set timer in exploit.timer is malformed. We remember that we have write access to this. Let's take a look at it.
The value for OnBootSec
is not set, which triggers the error.
We correct this by setting OnUnitActiveSec=0
and OnBootSec=0
. This triggers the service immediately after execution.
We run the service as follows, which copies the xxd
to /op
t and sets the SUID bit, recognisable by the red background.
Next, we specify which file we want to read. The first thing we are interested in is the root
flag. As mentioned, we can find out how to do this in GTFOBins. And we are able to read the root
flag.
To get a shell as root
, we have at least two ways available. Since we can not only read as root
with the xxd
binary with the SUID bit set, but also write as root
, we have the option of overwriting the /etc/shadow
file or overwriting the /root/.ssh/authorised_keys
file of root
. Both are briefly touched on.
First, we generate a simple password using OpenSSL using the following command:
The openssl passwd -1
command is used to generate a hashed version of a password. The passwd
utility within OpenSSL can generate password hashes in various formats, including the MD5-based hash (-1
flag). This is useful when you need to set or replace a password in files like /etc/shadow
, where the passwords are stored as hashes, not plaintext.
Next, we read the /etc/shadow
file using xxd
, for the correct format.
We craft the string from the hash and the info from the /etc/shadow
file.
Next, we just write it to the /etc/shadow
file. See GTFOBins for the command:
For confirmation, we read the file again.
We now just have to switch to root
with the new set password.
To write to /root/.ssh/authorized_keys
we set the LFILE
variable.
From our previous solution we use our ssh public key and write it to /root/.ssh/authorized_keys
using xxd
.
We are now able to log in as root
via SSH.
I originally wanted to read the SSH key of the root
user in /root/.ssh/id_rsa
, but unfortunately, this was not available.
Since this was not possible, the next idea was to extract the hashes from the /etc/shadow
file and to crack them but also without success.
Steps taken: